zoukankan      html  css  js  c++  java
  • POI 2012

    题意去八中看,很清晰。

     

    Festival:

    嘛,首先可以很轻松的建出差分约束的模型,然后强连通缩点之后发现不同块的点是没有联系的,于是可以每块分开做。每块的答案就是点与点之间距离的最大值,提前floyd处理即可。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 
      8 const int maxn=610;
      9 const int maxm=200010;
     10 const int INF=0x3f3f3f3f;
     11 
     12 int n,m1,m2,t,en,size,cnt,z[maxn],dfn[maxn],low[maxn],s[maxn],belong[maxn],dist[maxn][maxn];
     13 
     14 bool instack[maxn];
     15 
     16 struct edge
     17 {
     18     int e,d;
     19     edge *next;
     20 }*v[maxn],ed[maxm<<1];
     21 
     22 void add_edge(int s,int e,int d)
     23 {
     24     en++;
     25     ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
     26 }
     27 
     28 bool cmp(int a,int b)
     29 {
     30     return belong[a]<belong[b];
     31 }
     32 
     33 void dfs(int now)
     34 {
     35     t++;
     36     dfn[now]=low[now]=t;
     37     instack[now]=true;
     38     s[++size]=now;
     39     for (edge *e=v[now];e;e=e->next)
     40         if (!dfn[e->e])
     41         {
     42             dfs(e->e);
     43             low[now]=min(low[now],low[e->e]);
     44         }
     45         else
     46         {
     47             if (instack[e->e]) low[now]=min(low[now],dfn[e->e]);
     48         }
     49     if (dfn[now]==low[now])
     50     {
     51         cnt++;
     52         while (s[size]!=now)
     53         {
     54             belong[s[size]]=cnt;
     55             instack[s[size]]=false;
     56             size--;
     57         }
     58         belong[now]=cnt;
     59         instack[now]=false;
     60         size--;
     61     }
     62 }
     63 
     64 int main()
     65 {
     66     freopen("festival.in","r",stdin);
     67     freopen("festival.out","w",stdout);
     68 
     69     scanf("%d%d%d",&n,&m1,&m2);
     70     for (int a=1;a<=m1;a++)
     71     {
     72         int s,e;
     73         scanf("%d%d",&s,&e);
     74         add_edge(s,e,1);
     75         add_edge(e,s,-1);
     76     }
     77     for (int a=1;a<=m2;a++)
     78     {
     79         int s,e;
     80         scanf("%d%d",&s,&e);
     81         add_edge(s,e,0);
     82     }
     83     for (int a=1;a<=n;a++)
     84         if (!dfn[a]) dfs(a);
     85     for (int a=1;a<=n;a++)
     86         for (int b=1;b<=n;b++)
     87             dist[a][b]=-INF;
     88     for (int a=1;a<=n;a++)
     89         dist[a][a]=0;
     90     for (int a=1;a<=n;a++)
     91         for (edge *e=v[a];e;e=e->next)
     92             if (belong[a]==belong[e->e]) dist[a][e->e]=max(dist[a][e->e],e->d);
     93     for (int a=1;a<=n;a++)
     94         for (int b=1;b<=n;b++)
     95             if (dist[b][a]!=-INF)
     96                 for (int c=1;c<=n;c++)
     97                     if (dist[a][c]!=-INF) dist[b][c]=max(dist[b][c],dist[b][a]+dist[a][c]);
     98     for (int a=1;a<=n;a++)
     99         if (dist[a][a]>0)
    100         {
    101             printf("NIE
    ");
    102             return 0;
    103         }
    104     for (int a=1;a<=n;a++)
    105         z[a]=a;
    106     sort(z+1,z+n+1,cmp);
    107     int ans=0;
    108     for (int a=1;a<=n;)
    109     {
    110         int b=a;
    111         while (b<=n && belong[z[b]]==belong[z[a]])
    112             b++;
    113         int delta=0;
    114         for (int c=a;c<b;c++)
    115             for (int d=a;d<b;d++)
    116                 delta=max(delta,abs(dist[z[c]][z[d]]));
    117         ans+=delta+1;
    118         a=b;
    119     }
    120     printf("%d
    ",ans);
    121 
    122     return 0;
    123 }
    View Code

     

    Letters:

    每次找最近的一个字母移动过去就完了,树状数组维护。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 
     7 using namespace std;
     8 
     9 #ifdef unix
    10 #define LL "%lld"
    11 #else
    12 #define LL "%I64d"
    13 #endif
    14 
    15 #define lb(x) ((x)&(-(x)))
    16 
    17 const int maxn=1000010;
    18 
    19 int n,z[maxn],y[maxn],match[maxn];
    20 
    21 char s1[maxn],s2[maxn];
    22 
    23 queue<int> que1[26],que2[26];
    24 
    25 bool cmp(int a,int b)
    26 {
    27     return match[a]>match[b];
    28 }
    29 
    30 void modify(int p)
    31 {
    32     for (;p<=n;p+=lb(p))
    33         y[p]++;
    34 }
    35 
    36 int query(int p)
    37 {
    38     int ans=0;
    39     for (;p;p-=lb(p))
    40         ans+=y[p];
    41     return ans;
    42 }
    43 
    44 int main()
    45 {
    46     freopen("letters.in","r",stdin);
    47     freopen("letters.out","w",stdout);
    48 
    49     scanf("%d",&n);
    50     scanf("%s",s1+1);
    51     scanf("%s",s2+1);
    52     for (int a=1;a<=n;a++)
    53     {
    54         int c1=s1[a]-'A';
    55         int c2=s2[a]-'A';
    56         if (c1==c2 && !que1[c2].size() && !que2[c1].size()) match[a]=a;
    57         else
    58         {
    59             if (que2[c1].size())
    60             {
    61                 match[a]=que2[c1].front();
    62                 que2[c1].pop();
    63             }
    64             else que1[c1].push(a);
    65             if (que1[c2].size())
    66             {
    67                 match[que1[c2].front()]=a;
    68                 que1[c2].pop();
    69             }
    70             else que2[c2].push(a);
    71         }
    72     }
    73     for (int a=1;a<=n;a++)
    74         z[a]=a;
    75     sort(z+1,z+n+1,cmp);
    76     long long ans=0;
    77     for (int a=1;a<=n;a++)
    78     {
    79         int v=query(z[a]);
    80         int x=z[a]-v;
    81         ans+=abs(match[z[a]]-x);
    82         modify(z[a]);
    83     }
    84     printf(LL "
    ",ans);
    85 
    86     return 0;
    87 }
    View Code

     

    Distance:

    这题挺不错,枚举中间负责过渡的是也就是两数的最大公约数,然后向上将答案做出来。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn=100010;
     9 const int maxv=1000010;
    10 const int INF=0x3f3f3f3f;
    11 
    12 int n,z[maxn],cnt[maxv],pla[maxv],ans[maxv],res[maxv],rex[maxv],num[maxv];
    13 
    14 bool vis[maxv];
    15 
    16 int main()
    17 {
    18     freopen("distance.in","r",stdin);
    19     freopen("distance.out","w",stdout);
    20 
    21     scanf("%d",&n);
    22     int maxv=0;
    23     for (int a=1;a<=n;a++)
    24     {
    25         scanf("%d",&z[a]);
    26         cnt[z[a]]++;
    27         if (cnt[z[a]]==1) res[z[a]]=a;
    28         if (cnt[z[a]]==2) rex[z[a]]=a;
    29         maxv=max(maxv,z[a]);
    30     }
    31     for (int a=2;a<=maxv;a++)
    32         if (!vis[a])
    33         {
    34             for (int b=a;b<=maxv;b+=a)
    35             {
    36                 int c=b;
    37                 while (c%a==0)
    38                     num[b]++,c/=a;
    39                 vis[b]=true;
    40             }
    41         }
    42     memset(ans,0x3f,sizeof(ans));
    43     for (int a=1;a<=maxv;a++)
    44     {
    45         int minv1=INF,minv2=INF;
    46         int pla1=0,pla2=0;
    47         for (int b=a;b<=maxv;b+=a)
    48             if (cnt[b])
    49             {
    50                 if (num[b]-num[a]<minv1 || (num[b]-num[a]==minv1 && res[b]<res[pla1]))
    51                 {
    52                     minv2=minv1;pla2=pla1;
    53                     minv1=num[b]-num[a];pla1=b;
    54                 }
    55                 else
    56                 {
    57                     if (num[b]-num[a]<minv2 || (num[b]-num[a]==minv2 && res[b]<res[pla2]))
    58                     {
    59                         minv2=num[b]-num[a];
    60                         pla2=b;
    61                     }
    62                 }
    63             }
    64         if (pla2)
    65         {
    66             for (int b=a;b<=maxv;b+=a)
    67             {
    68                 int nowv=num[b]-num[a],nowp;
    69                 if (b==pla1) nowv+=minv2,nowp=pla2;
    70                 else nowv+=minv1,nowp=pla1;
    71                 if (nowv<ans[b] || (nowv==ans[b] && res[nowp]<res[pla[b]]))
    72                 {
    73                     ans[b]=nowv;
    74                     pla[b]=nowp;
    75                 }
    76             }
    77         }
    78     }
    79     for (int a=1;a<=n;a++)
    80         if (cnt[z[a]]>1)
    81         {
    82             if (a==res[z[a]]) printf("%d
    ",rex[z[a]]);
    83             else printf("%d
    ",res[z[a]]);
    84         }
    85         else printf("%d
    ",res[pla[z[a]]]);
    86 
    87     return 0;
    88 }
    View Code

     

    Rendezvous:

    一个一个地有向环套有向树,与处理完倍增神马的之后的就是简单的分情况讨论了。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 
      8 const int maxn=500010;
      9 
     10 int n,m,en,cnt,cir_len[maxn],f[maxn][20],q[maxn],depth[maxn],rt[maxn],belong[maxn],next[maxn],rank[maxn];
     11 
     12 bool cir[maxn];
     13 
     14 struct edge
     15 {
     16     int e;
     17     edge *next;
     18 }*v[maxn],ed[maxn];
     19 
     20 void add_edge(int s,int e)
     21 {
     22     en++;
     23     ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
     24 }
     25 
     26 void solve_lca(int root)
     27 {
     28     int front=1,tail=1;
     29     q[1]=root;
     30     depth[root]=1;
     31     rt[root]=root;
     32     for (;front<=tail;)
     33     {
     34         int now=q[front++];
     35         for (edge *e=v[now];e;e=e->next)
     36             if (!cir[e->e])
     37             {
     38                 depth[e->e]=depth[now]+1;
     39                 rt[e->e]=root;
     40                 belong[e->e]=cnt;
     41                 f[e->e][0]=now;
     42                 int p=now,x=0;
     43                 while (f[p][x])
     44                 {
     45                     f[e->e][x+1]=f[p][x];
     46                     p=f[p][x];
     47                     x++;
     48                 }
     49                 q[++tail]=e->e;
     50             }
     51     }
     52 }
     53 
     54 int get_lca(int p1,int p2)
     55 {
     56     if (depth[p1]<depth[p2]) swap(p1,p2);
     57     int delta=depth[p1]-depth[p2],x=0;
     58     while (delta)
     59     {
     60         if (delta&1) p1=f[p1][x];
     61         delta>>=1;
     62         x++;
     63     }
     64     x=0;
     65     while (p1!=p2)
     66     {
     67         if (!x || f[p1][x]!=f[p2][x])
     68         {
     69             p1=f[p1][x];
     70             p2=f[p2][x];
     71             x++;
     72         }
     73         else x--;
     74     }
     75     return p1;
     76 }
     77 
     78 int main()
     79 {
     80     freopen("rendezvous.in","r",stdin);
     81     freopen("rendezvous.out","w",stdout);
     82 
     83     scanf("%d%d",&n,&m);
     84     for (int a=1;a<=n;a++)
     85         scanf("%d",&next[a]),add_edge(next[a],a);
     86     for (int a=1;a<=n;a++)
     87         if (!belong[a])
     88         {
     89             cnt++;
     90             belong[a]=cnt;
     91             int p=a;
     92             while (true)
     93             {
     94                 p=next[p];
     95                 if (belong[p]) break;
     96                 belong[p]=cnt;
     97             }
     98             int px=p;
     99             int num=0;
    100             while (true)
    101             {
    102                 rank[px]=++num;
    103                 cir[px]=true;
    104                 px=next[px];
    105                 if (px==p) break;
    106             }
    107             cir_len[cnt]=num;
    108             px=p;
    109             while (true)
    110             {
    111                 solve_lca(px);
    112                 px=next[px];
    113                 if (px==p) break;
    114             }
    115         }
    116     for (int a=1;a<=m;a++)
    117     {
    118         int p1,p2;
    119         scanf("%d%d",&p1,&p2);
    120         if (belong[p1]!=belong[p2]) printf("-1 -1
    ");
    121         else
    122         {
    123             if (rt[p1]==rt[p2])
    124             {
    125                 int lca=get_lca(p1,p2);
    126                 printf("%d %d
    ",depth[p1]-depth[lca],depth[p2]-depth[lca]);
    127             }
    128             else
    129             {
    130                 int x1=depth[p1]-1,x2=depth[p2]-1;
    131                 p1=rt[p1];
    132                 p2=rt[p2];
    133                 int v1,v2,v3,v4;
    134                 v1=x1+(rank[p2]>rank[p1] ? rank[p2]-rank[p1] : rank[p2]+cir_len[belong[p1]]-rank[p1]);
    135                 v2=x2;
    136                 v3=x1;
    137                 v4=x2+(rank[p1]>rank[p2] ? rank[p1]-rank[p2] : rank[p1]+cir_len[belong[p2]]-rank[p2]);
    138                 if (max(v1,v2)==max(v3,v4))
    139                 {
    140                     if (min(v1,v2)==min(v3,v4))
    141                     {
    142                         if (v1<v2) swap(v1,v3),swap(v2,v4);
    143                     }
    144                     else
    145                     {
    146                         if (min(v1,v2)>min(v3,v4)) swap(v1,v3),swap(v2,v4);
    147                     }
    148                 }
    149                 else
    150                 {
    151                     if (max(v1,v2)>max(v3,v4)) swap(v1,v3),swap(v2,v4);
    152                 }
    153                 printf("%d %d
    ",v1,v2);
    154             }
    155         }
    156     }
    157 
    158     return 0;
    159 }
    View Code

     

    Well:

    二分答案。每次O(n)处理出每个位置所需要的代价。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<cctype>
      5 #include<algorithm>
      6 
      7 using namespace std;
      8 
      9 const int BUF_SIZE = 30;
     10 char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
     11   
     12 #define PTR_NEXT() 
     13     { 
     14         buf_s ++; 
     15         if (buf_s == buf_t) 
     16         { 
     17             buf_s = buf; 
     18             buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); 
     19         } 
     20     }
     21    
     22 #define readint(_n_) 
     23     { 
     24         while (*buf_s != '-' && !isdigit(*buf_s)) 
     25             PTR_NEXT(); 
     26         bool register _nega_ = false; 
     27         if (*buf_s == '-') 
     28         { 
     29             _nega_ = true; 
     30             PTR_NEXT(); 
     31         } 
     32         int register _x_ = 0; 
     33         while (isdigit(*buf_s)) 
     34         { 
     35             _x_ = _x_ * 10 + *buf_s - '0'; 
     36             PTR_NEXT(); 
     37         } 
     38         if (_nega_) 
     39             _x_ = -_x_; 
     40         (_n_) = (_x_); 
     41     }
     42 
     43 const int maxn=1000010;
     44 
     45 int n,cnt[maxn],z[maxn],y[maxn];
     46 
     47 long long m,value[maxn],num[maxn];
     48 
     49 int check(int delta)
     50 {
     51     for (int a=1;a<=n;a++)
     52         y[a]=z[a];
     53     long long use=0;
     54     for (int a=1;a<n;a++)
     55         if (y[a+1]-y[a]>delta)
     56         {
     57             use+=y[a+1]-y[a]-delta;
     58             y[a+1]=y[a]+delta;
     59         }
     60     for (int a=n;a>1;a--)
     61         if (y[a-1]-y[a]>delta)
     62         {
     63             use+=y[a-1]-y[a]-delta;
     64             y[a-1]=y[a]+delta;
     65         }
     66     if (use>m) return 0;
     67     memset(num,0,sizeof(num));
     68     memset(cnt,0,sizeof(cnt));
     69     for (int a=1;a<=n;a++)
     70     {
     71         int to=min(a+y[a]/delta,n);
     72         num[to]+=y[a]-(to-a)*delta;
     73         cnt[to]++;
     74         if (a!=1) num[a-1]-=y[a];
     75         cnt[a]--;
     76     }
     77     long long sum=0;
     78     int tot=0;
     79     for (int a=n;a>=1;a--)
     80     {
     81         sum+=num[a]+(long long)tot*delta;
     82         value[a]=sum;
     83         tot+=cnt[a];
     84     }
     85     memset(num,0,sizeof(num));
     86     memset(cnt,0,sizeof(cnt));
     87     for (int a=n;a>=1;a--)
     88     {
     89         int to=max(a-y[a]/delta,1);
     90         num[to]+=y[a]-(a-to)*delta;
     91         cnt[to]++;
     92         num[a]-=y[a];
     93         if (a!=1) cnt[a-1]--;
     94     }
     95     sum=0;
     96     tot=0;
     97     for (int a=1;a<=n;a++)
     98     {
     99         sum+=num[a]+(long long)tot*delta;
    100         value[a]+=sum;
    101         tot+=cnt[a];
    102     }
    103     for (int a=1;a<=n;a++)
    104         if (use+value[a]<=m) return a;
    105     return 0;
    106 }
    107 
    108 int main()
    109 {
    110     freopen("well.in","r",stdin);
    111     freopen("well.out","w",stdout);
    112 
    113     scanf("%d%lld",&n,&m);
    114     long long tot=0;
    115     int maxv=0;
    116     for (int a=1;a<=n;a++)
    117     {
    118         readint(z[a]);
    119         tot+=z[a];
    120         maxv=max(maxv,z[a]);
    121     }
    122     if (tot<=m)
    123     {
    124         printf("1 0
    ");
    125         return 0;
    126     }
    127     int l=0,r=maxv;
    128     while (l+1!=r)
    129     {
    130         int m=(l+r)>>1;
    131         if (check(m)==0) l=m;
    132         else r=m;
    133     }
    134     printf("%d %d
    ",check(r),r);
    135 
    136     return 0;
    137 }
    View Code

     

    Tour de Byteotia:

    并查集把环都判掉就行。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn=1000010;
     9 const int maxm=2000010;
    10 
    11 int n,m,k,ex[maxm][2],ans,cnt,f[maxn],res[maxm][2];
    12 
    13 int getf(int now)
    14 {
    15     if (f[now]==now) return now;
    16     else return f[now]=getf(f[now]);
    17 }
    18 
    19 int main()
    20 {
    21     freopen("tour.in","r",stdin);
    22     freopen("tour.out","w",stdout);
    23     
    24     scanf("%d%d%d",&n,&m,&k);
    25     for (int a=1;a<=n;a++)
    26         f[a]=a;
    27     for (int a=1;a<=m;a++)
    28     {
    29         int s,e;
    30         scanf("%d%d",&s,&e);
    31         if (s>e) swap(s,e);
    32         int f1=getf(s),f2=getf(e);
    33         if (s<=k && e<=k)
    34         {
    35             if (f1==f2) 
    36             {
    37                 ans++;
    38                 res[ans][0]=s;res[ans][1]=e;
    39             }
    40             else f[f1]=f2;
    41         }
    42         else
    43         {
    44             if (s>k) f[f1]=f2;
    45             else
    46             {
    47                 cnt++;
    48                 ex[cnt][0]=s;ex[cnt][1]=e;
    49             }
    50         }
    51     }
    52     for (int a=1;a<=cnt;a++)
    53     {
    54         int f1=getf(ex[a][0]),f2=getf(ex[a][1]);
    55         if (f1==f2) 
    56         {
    57             ans++;
    58             res[ans][0]=ex[a][0];
    59             res[ans][1]=ex[a][1];
    60         }
    61         else f[f1]=f2;
    62     }
    63     printf("%d
    ",ans);
    64     for (int a=1;a<=ans;a++)
    65         printf("%d %d
    ",res[a][0],res[a][1]);
    66 
    67     return 0;
    68 }
    View Code

     

    Vouchers:

    维护一下选某个值应该从哪个地方开始然后暴力就行了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn=1000010;
     9 
    10 int n,m,start[maxn];
    11 
    12 bool lucky[maxn],use[maxn];
    13 
    14 long long ans[maxn];
    15 
    16 int main()
    17 {
    18     freopen("vouchers.in","r",stdin);
    19     freopen("vouchers.out","w",stdout);
    20     
    21     scanf("%d",&m);
    22     int maxv=0;
    23     for (int a=1;a<=m;a++)
    24     {
    25         int v;
    26         scanf("%d",&v);
    27         lucky[v]=true;
    28         maxv=max(v,maxv);
    29     }
    30     scanf("%d",&n);
    31     long long tot=0;
    32     int cnt=0;
    33     for (int a=1;a<=maxv;a++)
    34         start[a]=a;
    35     for (int a=1;a<=n;a++)
    36     {
    37         int v;
    38         scanf("%d",&v);
    39         int p=start[v];
    40         for (int b=1;b<=v;b++)
    41         {
    42             while (p<=maxv && use[p])
    43                 p+=v;
    44             if (p>maxv) break;
    45             use[p]=true;
    46             if (lucky[p]) ans[++cnt]=tot+b;
    47         }
    48         start[v]=p;
    49         tot+=v;
    50     }
    51     printf("%d
    ",cnt);
    52     for (int a=1;a<=cnt;a++)
    53         printf("%lld
    ",ans[a]);
    54 
    55     return 0;
    56 }
    View Code

     

    A Horrible Poem:

    hash,对于每个长度只用枚举因子长度hash判断即可。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 
     7 using namespace std;
     8 
     9 #define ull unsigned long long
    10 
    11 const int maxn=500010;
    12 const ull base=10007;
    13 
    14 int n,m;
    15 
    16 ull bit[maxn],h[maxn];
    17 
    18 char s[maxn];
    19 
    20 bool check[maxn];
    21 
    22 vector < pair < int , int  > > prime[maxn];
    23 
    24 int calc(int l,int r)
    25 {
    26     return h[r]-h[l-1]*bit[r-l+1];
    27 }
    28 
    29 int main()
    30 {
    31     freopen("poem.in","r",stdin);
    32     freopen("poem.out","w",stdout);
    33 
    34     scanf("%d",&n);
    35     scanf("%s",s+1);
    36     for (int a=1;a<=n;a++)
    37         h[a]=h[a-1]*base+s[a];
    38     bit[0]=1;
    39     for (int a=1;a<=n;a++)
    40         bit[a]=bit[a-1]*base;
    41     for (int a=2;a<=n;a++)
    42         if (!check[a])
    43         {
    44             for (int b=a;b<=n;b+=a)
    45             {
    46                 int v=b;
    47                 int cnt=0;
    48                 while (v%a==0)
    49                     v/=a,cnt++;
    50                 prime[b].push_back(make_pair(a,cnt));
    51                 check[b]=true;
    52             }
    53         }
    54     scanf("%d",&m);
    55     for (int a=1;a<=m;a++)
    56     {
    57         int l,r;
    58         scanf("%d%d",&l,&r);
    59         int len=r-l+1;
    60         int ans=len;
    61         for (int b=0;b<(int)prime[len].size();b++)
    62         {
    63             int bx=prime[len][b].first;
    64             int cnt=prime[len][b].second;
    65             int mul=1;
    66             for (int c=1;c<=cnt;c++)
    67                 mul*=bx;
    68             for (;cnt--;)
    69             {
    70                 int lx=len/mul;
    71                 if (calc(l,r-lx)==calc(l+lx,r))
    72                 {
    73                     ans/=mul;
    74                     break;
    75                 }
    76                 mul/=bx;
    77             }
    78         }
    79         printf("%d
    ",ans);
    80     }
    81 
    82     return 0;
    83 }
    View Code

     

    Fibonacci Representation:

    直接记忆化搜索,每次只可能选择最相邻的两个斐波那契数。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<map>
     6 
     7 using namespace std;
     8 
     9 long long f[100];
    10 
    11 map<long long,int> ma;
    12 
    13 int dfs(long long v)
    14 {
    15     if (ma[v]) return ma[v];
    16     for (int a=1;a<=90;a++)
    17         if (f[a+1]>v)
    18         {
    19             if (f[a]==v) return ma[v]=1;
    20             return ma[v]=min(dfs(v-f[a]),dfs(f[a+1]-v))+1;
    21         }
    22     return -1;
    23 }
    24 
    25 int main()
    26 {
    27     freopen("fibonacci.in","r",stdin);
    28     freopen("fibonacci.out","w",stdout);
    29 
    30     f[1]=1;
    31     f[2]=2;
    32     for (int a=3;a<=90;a++)
    33         f[a]=f[a-1]+f[a-2];
    34     int t;
    35     scanf("%d",&t);
    36     for (int a=1;a<=t;a++)
    37     {
    38         long long v;
    39         scanf("%lld",&v);
    40         printf("%d
    ",dfs(v));
    41     }
    42 
    43     return 0;
    44 }
    View Code

     

    Squarks:

    最小的是a1+a2,其次是a1+a3,枚举a2+a3是谁,接下来的可以依次判断。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn=310;
     9 
    10 int n,m,res[maxn],ans[maxn][maxn],z[maxn*maxn],cnt;
    11 
    12 bool use[maxn*maxn];
    13 
    14 void check(int p)
    15 {
    16     memset(use,false,sizeof(use));
    17     if ((z[1]+z[2]+z[p])&1) return;
    18     res[1]=(z[1]+z[2]+z[p])/2-z[p];
    19     res[2]=z[1]-res[1];
    20     res[3]=z[2]-res[1];
    21     use[1]=use[2]=use[p]=true;
    22     for (int a=4,b=3;a<=n;a++)
    23     {
    24         while (b<=m && use[b])
    25             b++;
    26         if (b>m) return;
    27         res[a]=z[b]-res[1];
    28         use[b]=true;
    29         for (int c=2;c<a;c++)
    30         {
    31             if (res[c]>res[a]) return;
    32             int v=res[c]+res[a];
    33             int p=lower_bound(z+1,z+m+1,v)-z;
    34             if (z[p]!=v) return;
    35             int px=p;
    36             while (px && z[px]==z[p])
    37                 px--;
    38             px++;
    39             while (px<=m && z[px]==z[p] && use[px])
    40                 px++;
    41             if (z[px]!=z[p] || use[px]) return;
    42             p=px;
    43             use[p]=true;
    44         }
    45     }
    46     cnt++;
    47     for (int a=1;a<=n;a++)
    48         ans[cnt][a]=res[a];
    49 }
    50 
    51 int main()
    52 {
    53     freopen("squarks.in","r",stdin);
    54     freopen("squarks.out","w",stdout);
    55 
    56     scanf("%d",&n);
    57     m=n*(n-1)/2;
    58     for (int a=1;a<=m;a++)
    59         scanf("%d",&z[a]);
    60     sort(z+1,z+m+1);
    61     for (int a=3;a<=m;)
    62     {
    63         check(a);
    64         int b=a;
    65         while (b<=m && z[b]==z[a])
    66             b++;
    67         a=b;
    68     }
    69     printf("%d
    ",cnt);
    70     for (int a=1;a<=cnt;a++)
    71         for (int b=1;b<=n;b++)
    72         {
    73             printf("%d",ans[a][b]);
    74             if (b==n) printf("
    ");
    75             else printf(" ");
    76         }
    77 
    78     return 0;
    79 }
    View Code

     

    Bidding:

    由于x只有可能是2^a*3^b,所以可能性并不多,直接暴力DP就行了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include "cliclib.h"
     5 
     6 using namespace std;
     7 
     8 const int maxn=30010;
     9 
    10 int mul2[20],mul3[20];
    11 
    12 bool win[maxn][16][12];
    13 
    14 int main()
    15 {
    16     freopen("bidding.in","r",stdin);
    17     freopen("bidding.out","w",stdout);
    18 
    19     int n=inicjuj();
    20     int v=1,cnt1=0,cnt2=0;
    21     while (v<=n)
    22         mul2[cnt1++]=v,v<<=1;
    23     mul2[cnt1]=v;
    24     v=1;
    25     mul3[0]=1;
    26     while (v<=n)
    27         mul3[cnt2++]=v,v*=3;
    28     mul3[cnt2]=v;
    29     for (int a=n;a>=0;a--)
    30         for (int b=cnt1;b>=0;b--)
    31             for (int c=cnt2;c>=0;c--)
    32                 if (a+mul2[b]*mul3[c]<n)
    33                 {
    34                     if (b!=cnt1 && !win[a][b+1][c]) win[a][b][c]=true;
    35                     if (c!=cnt2 && !win[a][b][c+1]) win[a][b][c]=true;
    36                     if (!win[a+mul2[b]*mul3[c]][0][0]) win[a][b][c]=true;
    37                 }
    38     int sum=0,pow2=0,pow3=0;
    39     while(true)
    40     {
    41         if (pow2<cnt1 && !win[sum][pow2+1][pow3]) alojzy(2),pow2++;
    42         else
    43         {
    44             if (pow3<cnt2 && !win[sum][pow2][pow3+1]) alojzy(3),pow3++;
    45             else alojzy(1),sum+=mul2[pow2]*mul3[pow3],pow2=pow3=0;
    46         }
    47         int x=bajtazar();
    48         if (x==1) sum+=mul2[pow2]*mul3[pow3],pow2=pow3=0;
    49         if (x==2) pow2++;
    50         if (x==3) pow3++;
    51     }
    52 
    53     return 0;
    54 }
    View Code

     

    Salaries:

    做出每个点的上限,排序之后依次检验。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<cctype>
      5 #include<algorithm>
      6 
      7 using namespace std;
      8 
      9 const int BUF_SIZE = 30;
     10 char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
     11   
     12 #define PTR_NEXT() 
     13     { 
     14         buf_s ++; 
     15         if (buf_s == buf_t) 
     16         { 
     17             buf_s = buf; 
     18             buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); 
     19         } 
     20     }
     21    
     22 #define readint(_n_) 
     23     { 
     24         while (*buf_s != '-' && !isdigit(*buf_s)) 
     25             PTR_NEXT(); 
     26         bool register _nega_ = false; 
     27         if (*buf_s == '-') 
     28         { 
     29             _nega_ = true; 
     30             PTR_NEXT(); 
     31         } 
     32         int register _x_ = 0; 
     33         while (isdigit(*buf_s)) 
     34         { 
     35             _x_ = _x_ * 10 + *buf_s - '0'; 
     36             PTR_NEXT(); 
     37         } 
     38         if (_nega_) 
     39             _x_ = -_x_; 
     40         (_n_) = (_x_); 
     41     }
     42 
     43 const int maxn=1000010;
     44 
     45 int n,en,f[maxn],z[maxn],q[maxn],res[maxn],y[maxn],limit[maxn],show[maxn],x[maxn],last[maxn];
     46 
     47 struct edge
     48 {
     49     int e;
     50     edge *next;
     51 }*v[maxn],ed[maxn];
     52 
     53 void add_edge(int s,int e)
     54 {
     55     en++;
     56     ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
     57 }
     58 
     59 bool cmp(int a,int b)
     60 {
     61     return limit[a]<limit[b];
     62 }
     63 
     64 int main()
     65 {
     66     freopen("salaries.in","r",stdin);
     67     freopen("salaries.out","w",stdout);
     68 
     69     readint(n);
     70     int root;
     71     for (int a=1;a<=n;a++)
     72     {
     73         readint(f[a]);
     74         readint(z[a]);
     75         res[a]=z[a];
     76         show[z[a]]++;
     77         if (f[a]==a) root=a,f[a]=0;
     78         else add_edge(f[a],a);
     79     }
     80     for (int a=1;a<=n;a++)
     81         if (!show[a]) last[a]=a;
     82         else last[a]=last[a-1];
     83     int front=1,tail=1;
     84     q[1]=root;
     85     front=1,tail=1;
     86     int cnt=0;
     87     for (;front<=tail;)
     88     {
     89         int now=q[front++];
     90         for (edge *e=v[now];e;e=e->next)
     91         {
     92             q[++tail]=e->e;
     93             if (!z[e->e])
     94             {
     95                 y[++cnt]=e->e;
     96                 limit[e->e]=max(limit[now]-1,z[now]-1);
     97                 limit[e->e]=last[limit[e->e]];
     98             }
     99         }
    100     }
    101     res[root]=n;
    102     int maxv=0;
    103     memset(z,0,sizeof(z));
    104     for (int a=1;a<=cnt;a++)
    105     {
    106         z[limit[y[a]]]++;
    107         maxv=max(maxv,limit[y[a]]);
    108     }
    109     for (int a=1;a<=maxv;a++)
    110         z[a]+=z[a-1];
    111     for (int a=cnt;a>=1;a--)
    112         x[z[limit[y[a]]]--]=y[a];
    113     for (int a=1;a<=cnt;a++)
    114         y[a]=x[a];
    115     int tot=0,use=0;
    116     int hzc=0;
    117     for (int a=1,b=1;a<=cnt;a++)
    118     {
    119         int now=y[a];
    120         tot=limit[now];
    121         while (b<=tot)
    122         {
    123             if (!show[b]) x[++hzc]=b;
    124             else use++;
    125             b++;
    126         }
    127         if (limit[now]!=limit[y[a-1]] && tot-use==1) res[now]=x[hzc];
    128         use++;
    129     }
    130     for (int a=1;a<=n;a++)
    131         printf("%d
    ",res[a]);
    132 
    133     return 0;
    134 }
    View Code

    Leveling Ground:

    差分之后转化为单点,做出单点最小后统一正负号。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 
      7 using namespace std;
      8 
      9 #define calc(x,y,d) (abs(x-(long long)v2*d)+abs(y+(long long)v1*d))
     10 
     11 const int maxn=100010;
     12 
     13 int n,v1,v2,z[maxn];
     14 
     15 long long x[maxn],y[maxn];
     16 
     17 struct rec
     18 {
     19     int p;
     20     long long v;
     21     rec(){}
     22     rec(int a,long long b)
     23     {
     24         p=a;v=b;
     25     }
     26     bool operator<(const rec &a)const
     27     {
     28         return v>a.v;
     29     }
     30 };
     31 
     32 int gcd(int a,int b)
     33 {
     34     if (!b) return a;
     35     else return gcd(b,a%b);
     36 }
     37 
     38 int phi(int v)
     39 {
     40     int x=v;
     41     for (int a=2;a*a<=v;a++)
     42         if (v%a==0)
     43         {
     44             x=x/a*(a-1);
     45             while (v%a==0)
     46                 v/=a;
     47         }
     48     if (v!=1) x=x/v*(v-1);
     49     return x;
     50 }
     51 
     52 int mul(int a,int b,int mo)
     53 {
     54     int ans=1;
     55     while (b)
     56     {
     57         if (b&1) ans=(long long)ans*a%mo;
     58         a=(long long)a*a%mo;
     59         b>>=1;
     60     }
     61     return ans;
     62 }
     63 
     64 int main()
     65 {
     66     //freopen("ground.in","r",stdin);
     67     //freopen("ground.out","w",stdout);
     68 
     69     scanf("%d%d%d",&n,&v1,&v2);
     70     int g=gcd(v1,v2);
     71     for (int a=1;a<=n;a++)
     72     {
     73         scanf("%d",&z[a]);
     74         if (z[a]%g!=0)
     75         {
     76             printf("-1
    ");
     77             return 0;
     78         }
     79         z[a]/=g;
     80     }
     81     v1/=g;v2/=g;
     82     z[n+1]=-z[n];
     83     for (int a=n;a>1;a--)
     84         z[a]-=z[a-1];
     85     n++;
     86     if (v1==v2)
     87     {
     88         long long sum=0;
     89         for (int a=1;a<=n;a++)
     90             sum+=abs(z[a]);
     91         printf("%lld
    ",sum>>1);
     92         return 0;
     93     }
     94     if (v1>v2) swap(v1,v2);
     95     int x0=mul(v1,phi(v2)-1,v2);
     96     int y0=(-(long long)x0*v1+1)/v2;
     97     for (int a=1;a<=n;a++)
     98     {
     99         x[a]=(long long)x0*z[a];
    100         y[a]=(long long)y0*z[a];
    101         long long l=-z[a],r=z[a];
    102         if (l>r) swap(l,r);
    103         while (l+10<=r)
    104         {
    105             int dist=(r-l+1)/3;
    106             long long z1=calc(x[a],y[a],(l+dist));
    107             long long z2=calc(x[a],y[a],(r-dist));
    108             if (z1<=z2) r=r-dist;
    109             else l=l+dist;
    110         }
    111         long long minv=calc(x[a],y[a],r);
    112         int p=r;
    113         for (int b=l;b<r;b++)
    114         {
    115             long long value=calc(x[a],y[a],b);
    116             if (value<minv) minv=value,p=b;
    117         }
    118         x[a]=x[a]-(long long)p*v2;
    119         y[a]=y[a]+(long long)p*v1;
    120     }
    121     long long sum=0;
    122     for (int a=1;a<=n;a++)
    123         sum+=x[a];
    124     if (sum<0)
    125     {
    126         for (int a=1;a<=n;a++)
    127             swap(x[a],y[a]);
    128         swap(v1,v2);
    129         sum=0;
    130         for (int a=1;a<=n;a++)
    131             sum+=x[a];
    132     }
    133     sum/=v2;
    134     priority_queue<rec> heap;
    135     for (int a=1;a<=n;a++)
    136         heap.push(rec(a,abs(x[a]-v2)+abs(y[a]+v1)-abs(x[a])-abs(y[a])));
    137     for (int a=1;a<=sum;a++)
    138     {
    139         int p=heap.top().p;
    140         heap.pop();
    141         x[p]-=v2;
    142         y[p]+=v1;
    143         heap.push(rec(p,abs(x[p]-v2)+abs(y[p]+v1)-abs(x[p])-abs(y[p])));
    144     }
    145     long long ans=0;
    146     for (int a=1;a<=n;a++)
    147         ans+=abs(x[a])+abs(y[a]);
    148     printf("%lld
    ",ans>>1);
    149 
    150     return 0;
    151 }
    View Code

    Minimalist Security:

    每个联通块设个未知数,然后检验所有边。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 
      8 const int maxn=500010;
      9 const int maxm=6000010;
     10 
     11 int n,m,en,z[maxn],q[maxn];
     12 
     13 long long value[maxn][2];
     14 
     15 bool vis[maxn];
     16 
     17 struct edge
     18 {
     19     int e,d;
     20     edge *next;
     21 }*v[maxn],ed[maxm];
     22 
     23 void add_edge(int s,int e,int d)
     24 {
     25     en++;
     26     ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
     27 }
     28 
     29 int main()
     30 {
     31     freopen("security.in","r",stdin);
     32     freopen("security.out","w",stdout);
     33 
     34     scanf("%d%d",&n,&m);
     35     for (int a=1;a<=n;a++)
     36         scanf("%d",&z[a]);
     37     for (int a=1;a<=m;a++)
     38     {
     39         int s,e,d;
     40         scanf("%d%d%d",&s,&e,&d);
     41         add_edge(s,e,z[s]+z[e]-d);
     42         add_edge(e,s,z[s]+z[e]-d);
     43     }
     44     long long minv=0,maxv=0;
     45     for (int a=1;a<=n;a++)
     46         if (!vis[a])
     47         {
     48             long long L=0,R=z[a];
     49             vis[a]=true;
     50             int front=1,tail=1;
     51             q[1]=a;
     52             value[a][0]=1;value[a][1]=0;
     53             long long sum1=1,sum2=0;
     54             for (;front<=tail;)
     55             {
     56                 int now=q[front++];
     57                 for (edge *e=v[now];e;e=e->next)
     58                     if (!vis[e->e])
     59                     {
     60                         value[e->e][0]=-value[now][0];
     61                         value[e->e][1]=e->d-value[now][1];
     62                         if (value[e->e][0]>0)
     63                         {
     64                             L=max(L,(-value[e->e][1]-1)/value[e->e][0]+1);
     65                             R=min(R,(z[e->e]-value[e->e][1])/value[e->e][0]);
     66                         }
     67                         else
     68                         {
     69                             L=max(L,(value[e->e][1]-z[e->e]-1)/(-value[e->e][0])+1);
     70                             R=min(R,value[e->e][1]/(-value[e->e][0]));
     71                         }
     72                         sum1+=value[e->e][0];sum2+=value[e->e][1];
     73                         q[++tail]=e->e;
     74                         vis[e->e]=true;
     75                     }
     76                     else
     77                     {
     78                         long long v1=value[now][0]+value[e->e][0];
     79                         long long v2=value[now][1]+value[e->e][1];
     80                         if (v1==0)
     81                         {
     82                             if (v2!=e->d)
     83                             {
     84                                 printf("NIE
    ");
     85                                 return 0;
     86                             }
     87                         }
     88                         else
     89                         {
     90                             if ((v2-e->d)%v1!=0)
     91                             {
     92                                 printf("NIE
    ");
     93                                 return 0;
     94                             }
     95                             long long x=(e->d-v2)/v1;
     96                             L=max(L,x);
     97                             R=min(R,x);
     98                         }
     99                     }
    100             }
    101             if (L>R)
    102             {
    103                 printf("NIE
    ");
    104                 return 0;
    105             }
    106             long long v1=L*sum1+sum2;
    107             long long v2=R*sum1+sum2;
    108             minv+=min(v1,v2);
    109             maxv+=max(v1,v2);
    110         }
    111     printf("%lld %lld
    ",minv,maxv);
    112     
    113     return 0;
    114 }
    View Code

     

    Warehouse Store:

    这贪心已经考烂了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 
     7 using namespace std;
     8 
     9 const int maxn=250010;
    10 
    11 int n,res[maxn],v1[maxn],v2[maxn];
    12 
    13 struct rec
    14 {
    15     int id,v;
    16     rec(){}
    17     rec(int a,int b)
    18     {
    19         id=a;v=b;
    20     }
    21     bool operator<(const rec &a)const
    22     {
    23         return v<a.v;
    24     }
    25 };
    26 
    27 int main()
    28 {
    29     freopen("store.in","r",stdin);
    30     freopen("store.out","w",stdout);
    31 
    32     scanf("%d",&n);
    33     for (int a=1;a<=n;a++)
    34         scanf("%d",&v1[a]);
    35     for (int a=1;a<=n;a++)
    36         scanf("%d",&v2[a]);
    37     priority_queue<rec> heap;
    38     long long rest=0;
    39     for (int a=1;a<=n;a++)
    40     {
    41         rest+=v1[a];
    42         if (rest>=v2[a]) heap.push(rec(a,v2[a])),rest-=v2[a];
    43         else
    44         {
    45             if (heap.size() && heap.top().v>v2[a])
    46             {
    47                 rest+=heap.top().v;
    48                 rest-=v2[a];
    49                 heap.pop();
    50                 heap.push(rec(a,v2[a]));
    51             }
    52         }
    53     }
    54     int ans=0;
    55     while (heap.size())
    56         res[++ans]=heap.top().id,heap.pop();
    57     sort(res+1,res+ans+1);
    58     printf("%d
    ",ans);
    59     for (int a=1;a<=ans;a++)
    60     {
    61         printf("%d",res[a]);
    62         if (a==ans) printf("
    ");
    63         else printf(" ");
    64     }
    65 
    66     return 0;
    67 }
    View Code

     

    Prefixuffix:

    利用单调性使后面的检验做到O(N),卡hash。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn=1000010;
     9 const int base1=10007;
    10 const int mo1=1000000003;
    11 const int base2=10003;
    12 const int mo2=1000000007;
    13 
    14 int n,h1[maxn],bit1[maxn],h2[maxn],bit2[maxn];
    15 
    16 char s[maxn];
    17 
    18 pair<int,int> calc(int l,int r)
    19 {
    20     return make_pair((h1[r]-(long long)h1[l-1]*bit1[r-l+1]%mo1+mo1)%mo1,(h2[r]-(long long)h2[l-1]*bit2[r-l+1]%mo2+mo2)%mo2);
    21 }
    22 
    23 int main()
    24 {
    25     freopen("prefixuffix.in","r",stdin);
    26     freopen("prefixuffix.out","w",stdout);
    27 
    28     scanf("%d",&n);
    29     scanf("%s",s+1);
    30     for (int a=1;a<=n;a++)
    31         h1[a]=((long long)h1[a-1]*base1+s[a])%mo1;
    32     bit1[0]=1;
    33     for (int a=1;a<=n;a++)
    34         bit1[a]=(long long)bit1[a-1]*base1%mo1;
    35     for (int a=1;a<=n;a++)
    36         h2[a]=((long long)h2[a-1]*base2+s[a])%mo2;
    37     bit2[0]=1;
    38     for (int a=1;a<=n;a++)
    39         bit2[a]=(long long)bit2[a-1]*base2%mo2;
    40     int ans=0;
    41     for (int a=(n>>1),b=0;a>=0;a--)
    42     {
    43         b+=2;
    44         while (b && (a+b>(n>>1) || calc(a+1,a+b)!=calc(n-a-b+1,n-a)))
    45             b--;
    46         if (calc(1,a)==calc(n-a+1,n)) ans=max(ans,a+b);
    47     }
    48     printf("%d
    ",ans);
    49 
    50     return 0;
    51 }
    View Code

     

     

     

  • 相关阅读:
    I Hate It
    满减优惠[Offer收割]编程练习赛4
    积水的城市 hiho[Offer收割]编程练习赛4
    Subsequence 尺取法
    526. 优美的排列
    401. 二进制手表
    306. 累加数
    216. 组合总和 III
    131. 分割回文串
    ubuntu deepin-软件 分辨率的问题
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/3296612.html
Copyright © 2011-2022 走看看