zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 29(6/7)

    1、Quasi-palindrome

      题意:问一个字符串(你可以添加前导‘0’或不添加)是否是回文串

      思路:将给定的字符串的前缀‘0’和后缀‘0’都去掉,然后看其是否为回文串

     1 #include<iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int num;
     6     scanf("%d", &num);
     7     while (num / 10 != 0 && num % 10 == 0) num /= 10;
     8     int tmp = 0;
     9     int tnum = num;
    10     while (tnum)
    11     {
    12         tmp = tmp * 10 + tnum % 10;
    13         tnum /= 10;
    14     }
    15     if (tmp == num) printf("YES
    ");
    16     else printf("NO
    ");
    17 
    18     return 0;
    19 }
    View Code

    2、Kayaking

      题意:给出2*n个人的体重,有n-1辆双人车和2辆单人车,问每辆双人车上两个人的体重之差的和最小是多少

      思路:先把体重从小到大排序,然后枚举不坐双人车的两个人,算出剩下的人的最小体重差的和,取最小值。

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 int wt[120];
     5 const int INF = 1e9;
     6 int main()
     7 {
     8     int n;
     9     scanf("%d", &n);
    10     for (int i = 1; i <= 2 * n; i++)
    11     {
    12         scanf("%d", &wt[i]);
    13     }
    14     sort(wt + 1, wt + 2 * n + 1);
    15 
    16     int sum = INF;
    17     for (int i = 1; i < 2 * n; i++)
    18     {
    19         for (int j = i + 1; j <= 2 * n; j++)
    20         {
    21             int tsum = 0;
    22             for (int k = 1; k <= 2 * n;)
    23             {
    24                 while(k == i||k==j)
    25                 {
    26                     k++;
    27                 }
    28                 int w1 = wt[k];
    29                 k++;
    30                 while(k == j||k==i)
    31                 {
    32                     k++;
    33                 }
    34                 tsum += wt[k] - w1;
    35                 k++;
    36             }
    37             sum = min(sum, tsum);
    38         }
    39     }
    40     printf("%d
    ", sum);
    41     return 0;
    42 }
    View Code

    3、1-2-3

      题意:给出Alice和Bob的出拳依据及他们第一次的出拳,问k轮后Alice和Bob的得分

      思路:找到循环节。

      1 #include<iostream>
      2 #include<map>
      3 using namespace std;
      4 int alice[3][3];
      5 int bob[3][3];
      6 map<pair<int, int>, int>mp;
      7 map<int, pair<int, int> >score;
      8 int  a, b;
      9 long long k;
     10 int main()
     11 {
     12     scanf("%I64d%d%d", &k, &a, &b);
     13     for (int i = 0; i < 3; i++)
     14     {
     15         for (int j = 0; j < 3; j++)
     16         {
     17             scanf("%d", &alice[i][j]);
     18             alice[i][j]--;
     19         }
     20     }
     21     for (int i = 0; i < 3; i++)
     22     {
     23         for (int j = 0; j < 3; j++)
     24         {
     25             scanf("%d", &bob[i][j]);
     26             bob[i][j]--;
     27         }
     28     }
     29     int apoint = 0, bpoint = 0;
     30     int prea, preb;
     31     int kk = 0;
     32     int T,ta,tb,st;
     33     a--, b--;
     34     while (kk < k)
     35     {
     36         if (kk == 0)
     37         {
     38             prea = a;
     39             preb = b;
     40             if (a == 0 && b == 2|| a== 2 && b == 1||a==1&&b==0) apoint++;
     41             else if (b == 0 && a == 2 || b == 2 && a == 1 || b == 1 && a == 0)bpoint++;
     42             mp[make_pair(a, b)] = ++kk;
     43         }
     44         else
     45         {
     46             int aa = alice[prea][preb], bb = bob[prea][preb];
     47             if (st=mp[make_pair(aa, bb)])
     48             {
     49                 T = kk - st + 1;
     50                 pair<int, int>t1, t2;
     51                 if (T == 1)
     52                 {
     53                     t1 = score[st];
     54                     if (st > 1)
     55                     {
     56                         t2 = score[st - 1];
     57                         ta = t1.first - t2.first;
     58                         tb = t1.second - t2.second;
     59                     }
     60                     else
     61                     {
     62                         ta = t1.first, tb = t1.second;
     63                     }
     64                 }
     65                 else
     66                 {
     67                     if (st > 1)
     68                     {
     69                         t1 = score[st - 1];
     70                         t2 = score[kk];
     71                         ta = t2.first - t1.first;
     72                         tb = t2.second - t1.second;
     73                     }
     74                     else
     75                     {
     76                         t1 = score[kk];
     77                         ta = t1.first, tb = t1.second;
     78                     }
     79                 }
     80                 break;
     81             }
     82             if (aa == 0 && bb == 2 || aa == 2 && bb == 1 || aa == 1 && bb == 0) apoint++;
     83             else if (bb == 0 && aa == 2 || bb == 2 && aa == 1 || bb == 1 && aa == 0)bpoint++;
     84             mp[make_pair(aa, bb)] = ++kk;
     85             prea = aa, preb = bb;
     86         }
     87         score[kk] = make_pair(apoint, bpoint);
     88     }
     89     if (kk == k) printf("%d %d
    ", apoint, bpoint);
     90     else
     91     {
     92         long long suma = 0, sumb = 0;
     93         if (st == 1) suma += 1ll*k / T*ta, sumb += 1ll*k / T*tb;
     94         else
     95         {
     96             pair<int, int>tmp = score[st - 1];
     97             suma += tmp.first, sumb += tmp.second;
     98             k -= st-1;
     99             suma += 1ll * k / T*ta, sumb += 1ll * k / T*tb;
    100         }
    101         if (k%T)
    102         {
    103             if (st == 1)
    104             {
    105                 pair<int, int>t = score[k%T];
    106                 suma += t.first, sumb += t.second;
    107             }
    108             else
    109             {
    110                 pair<int, int>t1 = score[st-1];
    111                 pair<int, int>t2 = score[k%T+st-1];
    112                 suma += t2.first - t1.first, sumb += t2.second - t1.second;
    113             }
    114         }
    115         printf("%I64d %I64d
    ", suma, sumb);
    116     }
    117     return 0;
    118 }
    View Code

     4、Yet Another Array Queries Problem

      题意:对数组进行两种操作:1是将某个区间内的数左移(最左边移到的移到最右边);2是将某个区间内的数反转。给出初始数组和若干操作后,问若干下标位置的数是谁

      思路:对每一个所询问的下边的数,从最后一次操作向前找其对应的初始数组的下标。

     1 #include<iostream>
     2 using namespace std;
     3 int a[200010];
     4 struct node
     5 {
     6     int ff;
     7     int ll;
     8     int rr;
     9 }qq[200010];
    10 int main()
    11 {
    12     int n, q, m;
    13     scanf("%d%d%d", &n, &q, &m);
    14     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    15     for (int i = 1; i <= q; i++) scanf("%d%d%d", &qq[i].ff, &qq[i].ll, &qq[i].rr);
    16     for (int i = 1; i <= m; i++)
    17     {
    18         int pos;
    19         scanf("%d", &pos);
    20         for (int j = q; j >= 1; j--)
    21         {
    22             if (pos >= qq[j].ll&&pos <= qq[j].rr)
    23             {
    24                 if (qq[j].ff == 1)
    25                 {
    26                     if (pos > qq[j].ll) pos--;
    27                     else pos = qq[j].rr;
    28                 }
    29                 else
    30                 {
    31                     pos = qq[j].rr - (pos - qq[j].ll);
    32                 }
    33             }
    34         }
    35         if (i > 1) printf(" ");
    36         printf("%d", a[pos]);
    37     }
    38     printf("
    ");
    39     return 0;
    40 }
    View Code

    5、Turn Off The TV

      题意:有若干个区间,现在需要确定是否有多余的区间,使得在去掉这些区间后原本至少被一个区间覆盖的总长度不会减少。若存在,输出任意一个满足条件的区间的编号。

      思路:把区间按左端点排序,如果当前区间的右端点小于等于当前的最右端,则该区间就是多余区间;否则,如果当前区间的左端点比当前最右端还要大,则更新当前区间最左端和当前区间最右端;否则,如果当前区间的下一个区间和当前最左端和最右端构成的区间能够覆盖当前区间,则当前区间就是多余区间。

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 struct node
     5 {
     6     int ll;
     7     int rr;
     8     int idx;
     9 }tv[200010];
    10 bool Cmp(const node&a, const node&b)
    11 {
    12     if (a.ll == b.ll) return a.rr > b.rr;
    13     else return a.ll < b.ll;
    14 }
    15 int main()
    16 {
    17     int n;
    18     scanf("%d", &n);
    19     for (int i = 0; i < n; i++)
    20     {
    21         scanf("%d%d", &tv[i].ll, &tv[i].rr);
    22         tv[i].idx = i + 1;
    23     }
    24     sort(tv, tv + n, Cmp);
    25     int ans = -1;
    26     int tl = tv[0].ll, tr = tv[0].rr;
    27     for (int i = 1; i < n; i++)
    28     {
    29         if (tv[i].rr <= tr)
    30         {
    31             ans = i;
    32             break;
    33         }
    34         else if (tv[i].ll > tr)
    35         {
    36             tl = tv[i].ll;
    37             tr = tv[i].rr;
    38         }
    39         else
    40         {
    41             if (i + 1 < n&&tv[i + 1].ll <= tr+1&&tv[i + 1].rr >= tv[i].rr)
    42             {
    43                 ans = i;
    44                 break;
    45             }
    46             else
    47             {
    48                 tl = tv[i].ll;
    49                 tr = tv[i].rr;
    50             }
    51         }
    52     }
    53     if (ans == -1) printf("-1
    ");
    54     else printf("%d
    ", tv[ans].idx);
    55     return 0;
    56 }
    View Code

    6、Almost Permutation

      题意:你现在知道若干区间内的数是大于等于某一个数还是小于等于某一个数,然后定义cost为数组中每个数出现的次数的平方和,问最小的cost.

      思路:最小费用最大流。当所有条件都符合时(没有矛盾),将源点和每个index相连,容量为1,花费为0;将每个index和该index能够填的数字相连,容量为1,花费为0;对于每个数字,和汇点连n条边,容量1,花费为1、3、5、……、n*n-(n-1)(n-1)(如果当前这个数字出现k次,则需要向汇点连k条边,由于最小费用,肯定取最小花费的k条,由于前x条花费之和=x^2,即题目所要求的)

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<queue>
      4 #include<cstring>
      5 using namespace std;
      6 int maxlv[55];
      7 int minlv[55];
      8 int cnt[55];
      9 struct pp
     10 {
     11     int l;
     12     int r;
     13     int len;
     14 }p[55];
     15 
     16 //最小费用最大流模板
     17 #define MAXN 120  
     18 #define MAXM (2500*2+50)*2+100
     19 #define INF 0x3f3f3f3f  
     20 using namespace std;
     21 struct Edge
     22 {
     23     int from, to, cap, flow, cost, next;
     24     Edge(int fr = 0, int tt = 0, int ca = 0, int fl = 0, int ct = 0, int nt = 0) :from(fr), to(tt), cap(ca), flow(fl), cost(ct), next(nt)
     25     {
     26     };
     27 };
     28 Edge edge[MAXM];
     29 int Head[MAXN], edgenum;
     30 int pre[MAXN];//记录增广路径上 到达点i的边的编号  
     31 int dist[MAXN];
     32 bool vis[MAXN];
     33 int N;//点数
     34 //int M;//边数  
     35 int source, sink;//超级源点 超级汇点  
     36 void init(int numnode,int st,int sk)
     37 {
     38     N = numnode, source = st, sink = sk;
     39     edgenum = 0;
     40     memset(Head, -1, sizeof(Head));
     41 }
     42 void addEdge(int u, int v, int w, int c)
     43 {
     44     //Edge E1 = { u, v, w, 0, c, head[u] };
     45     //edge[edgenum] = E1;
     46     edge[edgenum] = Edge(u, v, w, 0, c, Head[u]);
     47     Head[u] = edgenum++;
     48     //Edge E2 = { v, u, 0, 0, -c, head[v] };
     49     //edge[edgenum] = E2;
     50     edge[edgenum] = Edge(v, u, 0, 0, -c, Head[v]);
     51     Head[v] = edgenum++;
     52 }
     53 bool SPFA(int s, int t)//寻找花销最少的路径  
     54 {
     55     //跑一遍SPFA 找s——t的最少花销路径 且该路径上每一条边不能满流  
     56     //若存在 说明可以继续增广,反之不能  
     57     queue<int> Q;
     58     memset(dist, INF, sizeof(dist));
     59     memset(vis, false, sizeof(vis));
     60     memset(pre, -1, sizeof(pre));
     61     dist[s] = 0;
     62     vis[s] = true;
     63     Q.push(s);
     64     while (!Q.empty())
     65     {
     66         int u = Q.front();
     67         Q.pop();
     68         vis[u] = false;
     69         for (int i = Head[u]; i != -1; i = edge[i].next)
     70         {
     71             Edge E = edge[i];
     72             if (dist[E.to] > dist[u] + E.cost && E.cap > E.flow)//可以松弛 且 没有满流  
     73             {
     74                 dist[E.to] = dist[u] + E.cost;
     75                 pre[E.to] = i;//记录前驱边 的编号  
     76                 if (!vis[E.to])
     77                 {
     78                     vis[E.to] = true;
     79                     Q.push(E.to);
     80                 }
     81             }
     82         }
     83     }
     84     return pre[t] != -1;//可达返回true  
     85 }
     86 void MCMF(int s, int t, int &cost, int &flow)
     87 {
     88     flow = 0;//总流量  
     89     cost = 0;//总费用  
     90     while (SPFA(s, t))//每次寻找花销最小的路径  
     91     {
     92         int Min = INF;
     93         //通过反向弧 在源点到汇点的最少花费路径 找最小增广流  
     94         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
     95         {
     96             Edge E = edge[i];
     97             Min = min(Min, E.cap - E.flow);
     98         }
     99         //增广  
    100         for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
    101         {
    102             edge[i].flow += Min;
    103             edge[i ^ 1].flow -= Min;
    104             cost += edge[i].cost * Min;//增广流的花销  
    105         }
    106         flow += Min;//总流量累加  
    107     }
    108 }
    109 
    110 int main()
    111 {
    112     int n,q;
    113     scanf("%d%d", &n, &q);
    114     for (int i = 1; i <= n; i++) maxlv[i] = n, minlv[i] = 1;
    115     bool flag = true;
    116     for (int i = 1; i <= q; i++)
    117     {
    118         int type, li, ri, vi;
    119         scanf("%d%d%d%d", &type, &li, &ri, &vi);
    120         if (!flag)continue;
    121         if (type == 1)
    122         {
    123             for (int j = li; j <= ri; j++)
    124             {
    125                 if (minlv[j] < vi) minlv[j] = vi;
    126                 if (minlv[j] > maxlv[j])
    127                 {
    128                     flag = false;
    129                     break;
    130                 }
    131             }
    132         }
    133         else
    134         {
    135             for (int j = li; j <= ri; j++)
    136             {
    137                 if (maxlv[j] > vi) maxlv[j] = vi;
    138                 if (maxlv[j] < minlv[j])
    139                 {
    140                     flag = false;
    141                     break;
    142                 }
    143             }
    144         }
    145     }
    146     if (!flag) printf("-1
    ");
    147     else
    148     {
    149         init(2 * n + 2, 0, 2 * n + 1);
    150         for (int i = 1; i <= n; i++)
    151         {
    152             addEdge(0, i, 1, 0);
    153         }
    154         for (int i = 1; i <= n; i++)
    155         {
    156             for (int j = minlv[i]; j <= maxlv[i]; j++)
    157             {
    158                 addEdge(i, n + j, 1, 0);
    159             }
    160         }
    161         for (int i = n + 1; i <= 2 * n; i++)
    162         {
    163             for (int j = 1; j <= n; j++)
    164             {
    165                 addEdge(i, 2 * n + 1, 1, j*j - (j - 1)*(j - 1));
    166             }
    167         }
    168         int totflow = 0, totcost = 0;
    169         MCMF(source, sink, totcost, totflow);
    170         //if (totcost < n) printf("-1
    ");
    171         //else printf("%d
    ", totcost);//之前flag判断是否可行也可用该步来替换
    172         printf("%d
    ", totcost);
    173     }
    174     return 0;
    175 }
    View Code
  • 相关阅读:
    对用户控件(ascx)属性(property)赋值
    The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
    图片淡入淡出切换效果
    在用户控件(ASCX)创建用户控件(ASCX)
    Login failed for user 'xxx'
    一些较好的书
    儿子购买的书
    怀念以前做网管的日子
    Linux下selinux简单梳理
    Rsync同步时删除多余文件 [附:删除大量文件方法的效率对比]
  • 原文地址:https://www.cnblogs.com/ivan-count/p/7679644.html
Copyright © 2011-2022 走看看