BYRBT

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\n");
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\n",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 "\n",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\n",rex[z[a]]);
83             else printf("%d\n",res[z[a]]);
84         }
85         else printf("%d\n",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\n");
121         else
122         {
123             if (rt[p1]==rt[p2])
124             {
125                 int lca=get_lca(p1,p2);
126                 printf("%d %d\n",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\n",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\n");
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\n",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\n",ans);
64     for (int a=1;a<=ans;a++)
65         printf("%d %d\n",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\n",cnt);
52     for (int a=1;a<=cnt;a++)
53         printf("%lld\n",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\n",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\n",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\n",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("\n");
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\n",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\n");
 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\n",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\n",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\n");
 85                                 return 0;
 86                             }
 87                         }
 88                         else
 89                         {
 90                             if ((v2-e->d)%v1!=0)
 91                             {
 92                                 printf("NIE\n");
 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\n");
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\n",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\n",ans);
59     for (int a=1;a<=ans;a++)
60     {
61         printf("%d",res[a]);
62         if (a==ans) printf("\n");
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\n",ans);
49 
50     return 0;
51 }
View Code

 

 

 

posted @ 2013-09-02 15:32  zhonghaoxi  阅读(1389)  评论(0编辑  收藏  举报
BYRBT