題意去八中看,很清晰。c++
Festival:git
嘛,首先能夠很輕鬆的建出差分約束的模型,而後強連通縮點以後發現不一樣塊的點是沒有聯繫的,因而能夠每塊分開作。每塊的答案就是點與點之間距離的最大值,提早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 }
Letters:ide
每次找最近的一個字母移動過去就完了,樹狀數組維護。spa
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 }
Distance:3d
這題挺不錯,枚舉中間負責過渡的是也就是兩數的最大公約數,而後向上將答案作出來。unix
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 }
Rendezvous:rest
一個一個地有向環套有向樹,與處理完倍增神馬的以後的就是簡單的分狀況討論了。code
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 }
Well:blog
二分答案。每次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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }