• 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) 【部分题解】


    A:因为删除是不计入操作次数的,所以转化一下就是求最长上升子序列,简单dp。

         设dp[i]表示前i个字符能凑成上升子序列的最大长度,dp[i] = max(dp[j]+1, dp[i]) 【j < i && s[j] < s[i]】

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 string s;
    14 int dp[105];
    15 
    16 int main()
    17 {
    18     //FIN;
    19     cin >> s;
    20     int len = s.size(), maxn = 0;
    21     rep(i, 1, len){
    22         dp[i] = 1;
    23         rep(j, 1, i-1){
    24             if(s[j-1] < s[i-1]) dp[i] = max(dp[j]+1, dp[i]);
    25         }
    26         maxn = max(maxn, dp[i]);
    27     }
    28     cout << 26-maxn << endl;
    29     return 0;
    30 }
    View Code

    B:可以看出题目其实就是让你求有多少对哑铃片,每一片哑铃只能用一次且这一对重量相同。

         最多只可能有14个哑铃片,因此我们可以用二进制进行枚举,假设二进制是 101011(高->低),那么表示1,2,4,6号哑铃片被选中了;

         这样的话最多 2^14种重量,接下来我们只需要判断一下相同重量的方案是不是满足每种哑铃片只用了一次。

         eg: 假设 1001和1100构成的重量是相同的,但是它们都选择了4号哑铃片,所以这种情况是不满足题意的,只有 1001和 0110这种情况满足;

         可见判断标准就是看两个方案的二进制数的按位与操作的结果是不是0,是的话表示满足,不是的话表示有重复使用,则不满足。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = (1<<16);
    12 
    13 int n, m;
    14 LL a[20], b[20];
    15 vector <LL> ans, ANS;
    16 map <LL, bool> vis, VIS;
    17 struct Node{
    18     int bt;
    19     LL val;
    20     bool operator < (const Node &r) const   { return val < r.val; }
    21 }node[N];
    22 
    23 bool judge(int i, int j){
    24     int a = node[i].bt, b = node[j].bt;
    25     if(a&b) return false;
    26     return true;
    27 }
    28 int main()
    29 {IO;
    30     //FIN;
    31     cin >> n >> m;
    32     rep(i, 1, n)    cin >> a[i];
    33     rep(i, 1, m)    cin >> b[i];
    34 
    35     rep(i, 0, ((1<<m)-1)){
    36         int bit = i, p = 1;
    37         LL res = 0;
    38         while(bit){
    39             if(bit&1)   res += b[p];
    40             p++; bit >>= 1;
    41         }
    42         node[i].val = res;
    43         node[i].bt = i;
    44     }
    45     sort(node, node+(1<<m));
    46     int i = 0;
    47     while(i < (1<<m)){
    48         int j = i+1;
    49         if(vis[node[i].val])    { i++; continue; }
    50         while(j < (1<<m)){
    51             if(node[i].val != node[j].val)  break;
    52             if(judge(i, j)){
    53                 if(!vis[node[i].val]) ans.pb(node[i].val);
    54                 vis[node[i].val] = true;
    55             }
    56             j++;
    57         }
    58         i++;
    59     }
    60     //rep(i, 0, (int)ans.size()-1)    cout << ans[i] << " ";
    61     rep(i, 1, n){
    62         if(!VIS[a[i]])  ANS.pb(a[i]);
    63         VIS[a[i]] = true;
    64         rep(j, 0, (int)ans.size()-1){
    65             LL res = a[i]+ans[j]*2;
    66             if(!VIS[res]) ANS.pb(res);
    67             VIS[res] = true;
    68         }
    69     }
    70     sort(ANS.begin(), ANS.end());
    71     rep(i, 0, (int)ANS.size()-1)    cout << ANS[i] << endl;
    72     return 0;
    73 }
    View Code

    C:貌似还没补。。。。。。

    D:这是一道贪心题,我们可以从左往右贪心。假设当前位置是pos,那么我们可以看一下pos往右的长度为r的区间内有几个摄像机,

         如果大于2,那么不需要放,否则需要放1个或2个。我们为了使摄像机充分利用,那么我们尽可能把摄像机给右边放,也就是说,

         我们从 pos+r-1 的位置往左扫,碰到没有摄像机的位置给它放就行了,知道 [pos, pos+r-1]这个区间的摄像机不少于2个就好。

         快速判断 [pos, pos+r-1]的摄像机个数,有的位置标记1,没有的标记0,那么区间求和就是摄像机个数;

         快速求区间和操作可以看看树状数组,当然可以用前缀和以及特殊的处理也可以搞定这个题。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e5+5;
    12 
    13 LL n, k, r, x, c[N];
    14 bool vis[N];
    15 
    16 int lowbit(int x)   { return x&-x; }
    17 void add(int id, int p){
    18     while(id <= n){
    19         c[id] += p;
    20         id += lowbit(id);
    21     }
    22 }
    23 LL sum(int id){
    24     LL ans = 0;
    25     while(id >= 1){
    26         ans += c[id];
    27         id -= lowbit(id);
    28     }
    29     return ans;
    30 }
    31 int main()
    32 {IO;
    33     //FIN;
    34     cin >> n >> k >> r;
    35     rep(i, 1, k)    { cin >> x; vis[x] = true; add(x, 1); }
    36     LL ans = 0;
    37     rep(i, 1, n-r+1){
    38         LL res = sum(i+r-1)-sum(i-1);
    39         if(res < 2){
    40             per(j, i+r-1, i){
    41                 if(res >= 2) break;
    42                 if(!vis[j]){
    43                     add(j, 1);
    44                     vis[j] = true;
    45                     ans++;
    46                     res++;
    47                 }
    48             }
    49         }
    50     }
    51     cout << ans << endl;
    52     return 0;
    53 }
    View Code

    E:按照题意,我们每次是从长度为k的序列中找罚时最小的来处理的,那么只需要用个优先队列,每次把最小的pop出来,然后按照题意进行模拟就行了。

         关于优先队列的用法请出门右拐百度 "STL 优先队列"

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int n, k, a[305];
    14 priority_queue<int, vector<int>, greater<int> > Q;
    15 
    16 int main()
    17 {
    18     //FIN;
    19     cin >> n >> k;
    20     rep(i, 1, n)    cin >> a[i];
    21     LL ans = 0, pre = 0, tol = 0;
    22     rep(i, 1, k)    Q.push(a[i]);
    23 
    24     int id = k+1;
    25     while(!Q.empty()){
    26         ans = pre+Q.top(); Q.pop();
    27         pre = ans;
    28         tol += ans;
    29         if(id <= n) { Q.push(a[id]); id++; }
    30     }
    31     cout << tol << endl;
    32     return 0;
    33 }
    View Code


    F:签到题,判断a + b = c,处理读入可以简化操作。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int a, b, c;
    14 
    15 int main()
    16 {
    17     scanf("%d + %d = %d", &a, &b, &c);
    18     if(a+b == c)    printf("YES
    ");
    19     else printf("NO
    ");
    20     return 0;
    21 }
    View Code

    G:苹果下落,按照题意模拟就行了。把每个苹果往下掉,直到不能掉为止。注意有坑点,有可能上下是多个苹果相连,

         那么如果判断条件不合理的话,最后结果只是最底下的一层掉落了。因此我们可以从下往上模拟就不会出现这个问题了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int n, m, G[55][55];
    14 string s;
    15 
    16 int main()
    17 {
    18     //FIN;
    19     cin >> n >> m;
    20     rep(i, 1, n){
    21         cin >> s;
    22         rep(j, 0, m-1){
    23             if(s[j] == 'o') G[i][j+1] = 0;
    24             if(s[j] == '#') G[i][j+1] = -1;
    25             if(s[j] == '.') G[i][j+1] = 1;
    26         }
    27     }
    28     per(i, n, 1){
    29         rep(j, 1, m){
    30             if(G[i][j] == 0){
    31                 int id = i+1;
    32                 while(id <= n && G[id][j] == 1) id++;
    33                 swap(G[i][j], G[id-1][j]);
    34             }
    35         }
    36     }
    37     rep(i, 1, n){
    38         rep(j, 1, m){
    39             if(G[i][j] == 0)    cout << 'o';
    40             if(G[i][j] == 1)    cout << '.';
    41             if(G[i][j] == -1)   cout << '#';
    42         }
    43         cout << endl;
    44     }
    45     return 0;
    46 }
    View Code

    H:题意是让你求L的联通块个数,C可以代表L或者W。这是个简单的搜索题,试想一下,如果我当前有个位置是L,那么我肯定这个联通块是存在的,

         那么往下搜索碰到C时,我如果把C当成L处理,对于我最后联通块的数目是只可能减少,不可能增加的。因为刚开始已经是一个L往下搜索,肯定是有一个联通块了,

         碰到C的,我可以吧 LCL这种连在一起,因此只减不增。

         使用到的技巧:可以每次dfs完了之后把经过的点变成W,这样以后就不用再走了。注意第一样例这种特殊判断的情况。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int n, m, res, G[55][55], dir[4][2] = {0,1,0,-1,1,0,-1,0};
    14 string s;
    15 
    16 bool judge(int x, int y){
    17     if(x < 1 || x > n || y < 1 || y > m || G[x][y] == -1)    return false;
    18     return true;
    19 }
    20 void dfs(int x, int y){
    21     rep(i, 0, 3){
    22         int xi = x+dir[i][0], yi = y+dir[i][1];
    23         if(judge(xi, yi)){
    24             G[xi][yi] = -1;
    25             dfs(xi, yi);
    26         }
    27     }
    28     return ;
    29 }
    30 int main()
    31 {
    32     //FIN;
    33     cin >> n >> m;
    34     rep(i, 1, n){
    35         cin >> s;
    36         rep(j, 0, m-1){
    37             if(s[j] == 'C') G[i][j+1] = 0;
    38             if(s[j] == 'W') G[i][j+1] = -1;
    39             if(s[j] == 'L') G[i][j+1] = 1;
    40         }
    41     }
    42     int ans = 0;
    43     rep(i, 1, n){
    44         rep(j, 1, m){
    45             if(G[i][j] == 1){
    46                 ans++;
    47                 dfs(i, j);
    48             }
    49         }
    50     }
    51     cout << ans << endl;
    52     return 0;
    53 }
    View Code

    I: 我们贪心的想一下,就可以发现,我能配对多少对袜子是和我的maxn和tol有关的。

         如果 tol/2 >= maxn,结果就是 tol/2, 否则的话结果就是 tol-maxn;具体可以多试几组数据画一画理解一下。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = (1<<16);
    12 
    13 int n;
    14 LL x;
    15 
    16 int main()
    17 {IO;
    18     //FIN;
    19     cin >> n;
    20     LL tol = 0, maxn = 0;
    21     rep(i, 1, n)    { cin >> x; maxn = max(maxn, x); tol += x; }
    22     cout << (tol >= maxn*2 ? tol/2 : tol-maxn) << endl;
    23     return 0;
    24 }
    View Code

    J:这也是一道贪心题,我们需要把位置大于0和小于0分开处理。对于每种情况,因为我们一趟所带的信封是固定的,

        所以我们肯定是想要把最远的位置跑的趟数尽可能少,那么只需要从远及近派送信封即可,每次送完信封还有剩余的时候,我们可以把它送给下一个位置。

        这样正负两种情况都处理一下就可以解决了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = (1<<16);
    12 
    13 int n;
    14 LL k;
    15 
    16 struct Node{
    17     int pos;
    18     LL c;
    19     bool operator < (const Node &r) const   { return pos < r.pos; }
    20 }node[1005];
    21 
    22 int main()
    23 {IO;
    24     //FIN;
    25     cin >> n >> k;
    26     rep(i, 1, n)    cin >> node[i].pos >> node[i].c;
    27     sort(node+1, node+n+1);
    28     LL ans = 0, res = 0;
    29     int i = n;
    30     while(i >= 1){
    31         if(node[i].pos < 0) break;
    32         LL cnt = (node[i].c+k-1)/k;
    33         ans += node[i].pos*cnt;
    34         LL sum = cnt*k;
    35         while(i >= 1 && sum && node[i].pos >= 0){
    36             if(node[i].c <= sum)    { sum -= node[i].c; i--; }
    37             else { node[i].c -= sum; break; }
    38         }
    39     }
    40     i = 1;
    41     while(i <= n){
    42         if(node[i].pos >= 0) break;
    43         LL cnt = (node[i].c+k-1)/k;
    44         ans -= node[i].pos*cnt;
    45         LL sum = k*cnt;
    46         while(i <= n && sum && node[i].pos < 0){
    47             if(node[i].c <= sum)    { sum -= node[i].c; i++; }
    48             else { node[i].c -= sum; break; }
    49         }
    50     }
    51     cout << ans*2 << endl;
    52     return 0;
    53 }
    View Code

    K:掷骰子判断a赢的概率,总共只有6*6=36种情况,最后的结果 ans = a赢 / (36 - 平局);高中简单概率计算题

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int a[10], b[10];
    14 
    15 int main()
    16 {
    17     //FIN;
    18     rep(i, 1, 6)    cin >> a[i];
    19     rep(i, 1, 6)    cin >> b[i];
    20     double cnt1 = 0, cnt2 = 0;
    21     rep(i, 1, 6){
    22         rep(j, 1, 6){
    23             if(a[i] > b[j]) cnt1++;
    24             if(a[i] == b[j])    cnt2++;
    25         }
    26     }
    27     printf("%.5lf
    ", cnt1*1.0/(36-cnt2));
    28     return 0;
    29 }
    View Code

    L:可以知道,只有三种矩形,那么无论怎么拼,其中的最长边才有可能是最后正方形的边长的,基于这一点,可以分类讨论一下。

     1 #include<bits/stdc++.h>
     2 #define  IO ios_base::sync_with_stadio(0);cin.tie(0);
     3 using namespace std;
     4 int a[55][55];
     5 int main()
     6 {
     7     int a1, b1, a2, b2, a3, b3;
     8     while(cin >> a1 >> b1 >> a2 >> b2 >> a3 >> b3){
     9         int a = max(a1, b1);
    10         int b = max(a2, b2);
    11         int c = max(a3, b3);
    12         int d = a, flag = 1;
    13         if(b > d){d = b; flag = 2;}
    14         if(c > d){d = c; flag = 3;}
    15         if(flag == 1){
    16             int e = a2 + a3;
    17             int f = a2 + b3;
    18             int g = b2 + a3;
    19             int h = b2 + b3;
    20             if(e == d){
    21                 if(b2 == b3 && (b2 + a1 == d || b2 + b1 == d)){ cout << "YES" << endl; continue;}
    22             }
    23             if(f == d){
    24                 if(b2 == a3 && (b2 + a1 == d || b2 + b1 == d)) { cout << "YES" << endl; continue;}
    25             }
    26              if(g == d){
    27                 if(a2 == b3 && (a2 + a1 == d || a2 + b1 == d)) { cout << "YES" << endl; continue;}
    28             }
    29              if(h == d){
    30                 if(a2 == a3 && (a2 + a1 == d || a2 + b1 == d)) { cout << "YES" << endl; continue;}
    31             }
    32         }
    33         else if(flag == 2){
    34             int e = a1 + a3;
    35             int f = a1 + b3;
    36             int g = b1 + a3;
    37             int h = b1 + b3;
    38             if(e == d){
    39                 if(b1 == b3 && (b1 + a2 == d || b1 + b2 == d)){ cout << "YES" << endl; continue;}
    40             }
    41             if(f == d){
    42                 if(b1 == a3 && (b1 + a2 == d || b1 + b2 == d)) { cout << "YES" << endl; continue;}
    43             }
    44              if(g == d){
    45                 if(a1 == b3 && (a1 + a2 == d || a1 + b2 == d)) { cout << "YES" << endl; continue;}
    46             }
    47              if(h == d){
    48                 if(a1 == a3 && (a1 + a2 == d || a1 + b2 == d)) { cout << "YES" << endl; continue;}
    49             }
    50         }
    51         else if(flag == 3){
    52             int e = a2 + a1;
    53             int f = a2 + b1;
    54             int g = b2 + a1;
    55             int h = b2 + b1;
    56             if(e == d){
    57                 if(b2 == b1 && (b1 + a3 == d || b1 + b3 == d)){ cout << "YES" << endl; continue;}
    58             }
    59             if(f == d){
    60                 if(b2 == a1 && (b2 + a3 == d || b2 + b3 == d)) { cout << "YES" << endl; continue;}
    61             }
    62              if(g == d){
    63                 if(a2 == b1 && (b1 + a3 == d || b1 + b3 == d)) { cout << "YES" << endl; continue;}
    64             }
    65              if(h == d){
    66                 if(a2 == a1 && (a1 + a3 == d || a1 + b3 == d)) { cout << "YES" << endl; continue;}
    67             }
    68         }
    69         cout << "NO" << endl;
    70     }
    71 }
    View Code

    M:题意是让你找最长交错子序列,这个序列是上升下降或者下降上升交错出现的。其实这个题的本质和A的最长上升子序列是一样的,

         最长上升是在每个位置i我们找的是i之前的最长上升,这道题换成了两种情况

         一种情况是假设当前要上升的话,我们找i之前的最长下降。另一种是假设当前下降,我们找i之前的最长上升,用两个dp数组就可以解决了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
     4 #define per(i,a,b) for(int i = a;i >= b;-- i)
     5 #define mem(a,b) memset((a),(b),sizeof((a)))
     6 #define FIN freopen("in.txt","r",stdin)
     7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     8 #define pb push_back
     9 typedef long long LL;
    10 typedef pair<int, LL> PIR;
    11 const int N = 1e6+5;
    12 
    13 int n, a[55], dp[55][2];
    14 
    15 int main()
    16 {
    17     //FIN;
    18     cin >> n;
    19     rep(i, 1, n)    cin >> a[i];
    20     int maxn = 1;
    21     rep(i, 1, n){
    22         dp[i][0] = dp[i][1] = 1;
    23         rep(j, 1, i-1){
    24             if(a[j] > a[i]) dp[i][0] = max(dp[i][0], dp[j][1]+1);
    25             if(a[j] < a[i]) dp[i][1] = max(dp[i][1], dp[j][0]+1);
    26         }
    27         maxn = max(maxn, max(dp[i][0], dp[i][1]));
    28     }
    29     cout << maxn << endl;
    30     return 0;
    31 }
    View Code

         

  • 相关阅读:
    xfire webServeic 例子
    Spring3 url匹配规则
    js 字符串转化成数字
    JS回车事件,兼容目前所有浏览器
    笔记:Zygote和SystemServer进程启动过程
    安卓Task和Back Stack
    札记:Property动画
    札记:翻译-使用Scene和Transition实现【场景切换】动画效果
    算法:排序
    [BOT]自定义ViewPagerStripIndicator
  • 原文地址:https://www.cnblogs.com/Jstyle-continue/p/6662413.html
Copyright © 2020-2023  润新知