Codeforces Round #788 (Div. 2) 题解。
实况在这里 
 
A. Prof. Slim 题目描述: 
题目分析 给你一个序列,一次操作会使序列中的两个数交换符号但不交换大小,问能否在若干次操作后使得序列不递减。容易得到负数的个数一定不变并且负数永远小于正数,因此最后的结果一定是负数全在前面,正数全在后面,因为一个位置的数的绝对值一定不会改变,所以可以得到在绝对值中,负数区域一定不递增,正数区域一定不递减。先 O(n) 统计所有的负数的个数,再判断就ok了。
标程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <bits/stdc++.h>  #define  maxn 200005 #define  maxx 40005 #define  OK {puts("YES" );} #define  NO {puts("NO" );return;} using  namespace  std;char  s[maxn];int  a[maxn],b[maxn]; int  n,k;void  solve ()  {    cin>>n;     int  num_de=0 ;     for (int  i=1 ;i<=n;i++){         scanf ("%d" ,&a[i]);         if (a[i]<0 ){             num_de++;         }     }     for (int  i=2 ;i<=num_de;i++){         if (abs (a[i])-abs (a[i-1 ])>0 )NO     }     for (int  i=num_de+2 ;i<=n;i++){         if (abs (a[i])-abs (a[i-1 ])<0 )NO     }     OK           } void  init ()  {     }  signed  main ()  {    #ifndef  ONLINE_JUDGE          freopen ("1.in" ,"r" ,stdin);     #endif       int  t=1 ;     cin>>t;     init ();     while (t--)solve ();          return  0 ; } 
 
B. Dorms War 题目描述: 
题目分析 这题目题意分析了很久,后面看了很久才看出来。就是说给你一个字符串和若干个特殊字符,每次操作会使得特殊字符前面的那个字符消失,直到字符不会再消失为止,问你一共消失几次,特殊字符可以被前面的特殊字符消除。
其实不难发现,一个特殊字符吞前面字符的次数就相当于它距离最近的一个特殊字符的距离+1。多个特殊字符不影响结果,取最大即可,明明是 O(n) 的算法,写的时间却很高,甚至因此 T 了一次。以后一定要记得 IO 优化,拒绝 cin,从我做起。
标程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h>  #define  maxn 200005 #define  maxx 40005 #define  OK {puts("YES" );} #define  NO {puts("NO" );return;} using  namespace  std;char  s[maxn];int  a[maxn],b[maxn]; int  spec[100 ];int  n,k;void  solve ()  {    scanf ("%d" ,&n);     scanf ("%s" ,s);     scanf ("%d" ,&k);     memset (spec,0 ,sizeof (spec));     string tmp;     for (int  i=1 ;i<=k;i++){         cin>>tmp;         spec[tmp[0 ]-'a' ]=1 ;     }     int  cnt=0 ;     int  ans=0 ;     for (int  i=0 ;i<n;i++){         if (spec[s[i]-'a' ]){             ans=max (ans,cnt);             cnt=0 ;         }         cnt++;     }          printf ("%d\n" ,ans); } void  init ()  {     }  signed  main ()  {    #ifndef  ONLINE_JUDGE          freopen ("1.in" ,"r" ,stdin);     #endif       int  t=1 ;     cin>>t;     init ();     while (t--)solve ();                    return  0 ; } 
 
C. Where is the Pizza? 题目描述 
题目分析 选择其中一个数导致了另一个必然不选,所以这里又要选另一个必选的数,然后对于每个环只有两种方案,找到环个数相乘a和b用散列保存位置。b数组全部指向a。a数组指向 自己那个值在 b 中的位置。每次判断 这个环中的位置对应的 c是否全为0。最后特判两个相等的时候这个情况也不 乘2。
标程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include <bits/stdc++.h>  #define  maxn 100005 #define  maxx 40005 #define  OK {puts("YES" );} #define  NO {puts("NO" );return;} using  namespace  std;char  s[maxn];int  a[maxn],b[maxn],a_[maxn],b_[maxn],c[maxn],vis[maxn]; int  spec[100 ];int  n,k;const  int  mod=1e9 +7 ;queue<int >q; int  dfs (int  pos)  {    int  flag=1 ;     q.push (pos);     while (q.size ()){         int  x=q.front ();         q.pop ();         if (!vis[x]){             vis[x]=1 ;             q.push (b_[a[x]]);             q.push (a_[b[x]]);         }         if (c[x]){             flag=0 ;         }         if (a[x]==b[x]){             flag=0 ;         }     }     return  flag;      } void  solve ()  {    int  n;     cin>>n;     long  long  ans=1 ;     memset (vis,0 ,sizeof (int )*(n+1 ));     for (int  i=1 ;i<=n;i++){         cin>>a[i];         a_[a[i]]=i;     }     for (int  i=1 ;i<=n;i++){         cin>>b[i];         b_[b[i]]=i;     }     for (int  i=1 ;i<=n;i++){         cin>>c[i];         }     for (int  i=1 ;i<=n;i++){         if (!vis[i]){             int  res=dfs (i);             if (res){                 ans*=2 ;                 ans%=mod;             }         }     }     printf ("%lld\n" ,ans);      } void  init ()  {     }  signed  main ()  {    ios::sync_with_stdio (0 );     cin.tie (0 );     cout.tie (0 );     #ifndef  ONLINE_JUDGE          freopen ("1.in" ,"r" ,stdin);     #endif       int  t=1 ;     cin>>t;     init ();     while (t--)solve ();                    return  0 ; } 
 
D. Very Suspicious 题目描述 
题目分析 计算几何,自己画一下会发现:三线相交得到6个,两线相交得到2个,线只有三种方向。每添加一条线凑成三线相交,方案数+4,与其它不平行的线相交,每多一个方案数+2。然后打一遍表,把 1e9 以内的答案跑出来最后二分寻找答案即可。
标程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <bits/stdc++.h>  #define  maxn 100005 #define  maxx 40005 #define  OK {puts("YES" );} #define  NO {puts("NO" );return;} using  namespace  std;char  s[maxn];int  a[maxn],b[maxn],a_[maxn],b_[maxn],c[maxn],vis[maxn]; int  ans[maxn];void  solve ()  {    int  n;     cin>>n;     int  d=lower_bound (ans,ans+maxn,n)-ans;     printf ("%d\n" ,d); } void  init ()  {    int  num[3 ]={2 ,1 ,1 };     memset (ans,0x3f ,sizeof (ans));     ans[0 ]=0 ;     ans[1 ]=0 ;     ans[2 ]=2 ;     ans[3 ]=6 ;     ans[4 ]=10 ;     int  cnt=10 ;     int  i=4 ;     for (;cnt<=1e9 ;i++){         int  sel=i%3 ;         cnt+=(num[(sel+1 )%3 ]+num[(sel+2 )%3 ]-2 )*2 ;         cnt+=4 ;         num[sel]++;         ans[i+1 ]=cnt;     } }  signed  main ()  {    ios::sync_with_stdio (0 );     cin.tie (0 );     cout.tie (0 );     #ifndef  ONLINE_JUDGE          freopen ("1.in" ,"r" ,stdin);     #endif       int  t=1 ;     cin>>t;     init ();     while (t--)solve ();                    return  0 ; } 
 
这波也是上大分,上了38分,希望再接再厉,争取快点上紫。