POI 2012

題意去八中看,很清晰。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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
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
相關文章
相關標籤/搜索