POI 2010
Guilds:
孤立点无解,剩下的乱染色就行了。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<cctype>
5
6 using namespace std;
7
8 const int BUF_SIZE = 30;
9 char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
10
11 #define PTR_NEXT() \
12 { \
13 buf_s ++; \
14 if (buf_s == buf_t) \
15 { \
16 buf_s = buf; \
17 buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); \
18 } \
19 }
20
21 #define readint(_n_) \
22 { \
23 while (*buf_s != '-' && !isdigit(*buf_s)) \
24 PTR_NEXT(); \
25 bool register _nega_ = false; \
26 if (*buf_s == '-') \
27 { \
28 _nega_ = true; \
29 PTR_NEXT(); \
30 } \
31 int register _x_ = 0; \
32 while (isdigit(*buf_s)) \
33 { \
34 _x_ = _x_ * 10 + *buf_s - '0'; \
35 PTR_NEXT(); \
36 } \
37 if (_nega_) \
38 _x_ = -_x_; \
39 (_n_) = (_x_); \
40 }
41
42 const int maxn=200010;
43 const int maxm=500010;
44
45 int n,m,en,res[maxn],q[maxn];
46
47 bool use[maxn];
48
49 struct edge
50 {
51 int e;
52 edge *next;
53 }*v[maxn],ed[maxm<<1];
54
55 void add_edge(int s,int e)
56 {
57 en++;
58 ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
59 }
60
61 int main()
62 {
63 freopen("guilds.in","r",stdin);
64 freopen("guilds.out","w",stdout);
65
66 readint(n);
67 readint(m);
68 int s,e;
69 for (int a=1;a<=m;a++)
70 {
71 readint(s);
72 readint(e);
73 add_edge(s,e);
74 add_edge(e,s);
75 use[s]=use[e]=true;
76 }
77 for (int a=1;a<=n;a++)
78 if (!use[a])
79 {
80 printf("NIE\n");
81 return 0;
82 }
83 printf("TAK\n");
84 for (int a=1;a<=n;a++)
85 if (!res[a])
86 {
87 res[a]=1;
88 int front=1,tail=1;
89 q[1]=a;
90 for (;front<=tail;)
91 {
92 int now=q[front++];
93 for (edge *e=v[now];e;e=e->next)
94 if (!res[e->e])
95 {
96 res[e->e]=3-res[now];
97 q[++tail]=e->e;
98 }
99 }
100 }
101 for (int a=1;a<=n;a++)
102 if (res[a]==1) printf("K\n");
103 else printf("S\n");
104
105 return 0;
106 }
Beads:
直接枚举长度检验即可。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<set>
5 #include<vector>
6
7 using namespace std;
8
9 #define ull unsigned long long
10
11 const int maxn=200010;
12 const ull base=999997;
13
14 int n,z[maxn];
15
16 ull h1[maxn],h2[maxn],bit[maxn];
17
18 vector<int> res;
19
20 ull calc1(int l,int r)
21 {
22 return h1[r]-h1[l-1]*bit[r-l+1];
23 }
24
25 ull calc2(int l,int r)
26 {
27 return h2[l]-h2[r+1]*bit[r-l+1];
28 }
29
30 int calc(int l)
31 {
32 set<ull> se;
33 for (int a=1;a+l-1<=n;a+=l)
34 se.insert(min(calc1(a,a+l-1),calc2(a,a+l-1)));
35 return (int)se.size();
36 }
37
38 int main()
39 {
40 freopen("beads.in","r",stdin);
41 freopen("beads.out","w",stdout);
42
43 scanf("%d",&n);
44 for (int a=1;a<=n;a++)
45 scanf("%d",&z[a]);
46 bit[0]=1;
47 for (int a=1;a<=n;a++)
48 bit[a]=bit[a-1]*base;
49 for (int a=1;a<=n;a++)
50 h1[a]=h1[a-1]*base+z[a];
51 for (int a=n;a>=1;a--)
52 h2[a]=h2[a+1]*base+z[a];
53 int ans=0;
54 for (int a=1;a<=n;a++)
55 {
56 int v=calc(a);
57 if (v>ans)
58 {
59 ans=v;
60 res.clear();
61 }
62 if (v==ans) res.push_back(a);
63 }
64 printf("%d %d\n",ans,(int)res.size());
65 for (int a=0;a<(int)res.size();a++)
66 {
67 printf("%d",res[a]);
68 if (a==(int)res.size()-1) printf("\n");
69 else printf(" ");
70 }
71
72 return 0;
73 }
Divine Divisors:
首先预处理出所有1-10^6之类的质数并且把所有的数的该部分因子去除,那么剩下的所有数的可能性就只有:p、p^2、pq这三种可能性。第一种可以直接使用miller rabin判断即可(要用快速加法)。第二种也可以直接处理。第三种可以先处理出所有最大公约数再直接算贡献即可。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<cmath>
5
6 using namespace std;
7
8 #ifdef unix
9 #define LL "%lld"
10 #else
11 #define LL "%I64d"
12 #endif
13
14 const int maxn=610;
15 const int maxp=1000010;
16 const int prime_check[]={0,2,3,11,67};
17
18 int n,cnt,p[maxp],num[maxp],y[maxn];
19
20 long long z[maxn];
21
22 bool use[maxp];
23
24 long long gcd(long long a,long long b)
25 {
26 if (!b) return a;
27 else return gcd(b,a%b);
28 }
29
30 long long add(long long a,long long b,long long c)
31 {
32 long long ans=0;
33 while (b)
34 {
35 if (b&1)
36 {
37 ans+=a;
38 if (ans>=c) ans-=c;
39 }
40 a+=a;
41 if (a>=c) a-=c;
42 b>>=1;
43 }
44 return ans;
45 }
46
47 long long mul(long long a,long long b,long long c)
48 {
49 long long ans=1;
50 while (b)
51 {
52 if (b&1) ans=add(ans,a,c);
53 a=add(a,a,c);
54 b>>=1;
55 }
56 return ans;
57 }
58
59 bool prime(long long n)
60 {
61 if (n<2) return false;
62 if (n==2) return true;
63 if (!(n&1)) return false;
64 long long d=n,r=0;
65 d--;
66 while (!(d&1))
67 {
68 r++;
69 d>>=1;
70 }
71 for (int a=1;a<=4;a++)
72 {
73 long long now=prime_check[a];
74 if (now==n) continue;
75 long long v=mul(now,d,n);
76 if (v==1 || v==n-1) continue;
77 bool find=false;
78 for (int b=1;b<r && !find;b++)
79 {
80 v=add(v,v,n);
81 if (v==n-1) find=true;
82 }
83 if (!find) return false;
84 }
85 return true;
86 }
87
88 bool call_prime(long long v)
89 {
90 if (v<2) return false;
91 for (long long a=2;a*a<=v;a++)
92 if (v%a==0) return false;
93 return true;
94 }
95
96 int main()
97 {
98 freopen("divine.in","r",stdin);
99 freopen("divine.out","w",stdout);
100
101 for (int a=2;a<=1000000;a++)
102 {
103 if (!use[a])
104 {
105 cnt++;
106 p[cnt]=a;
107 }
108 for (int b=1;p[b]*a<=1000000;b++)
109 {
110 use[p[b]*a]=true;
111 if (a%p[b]==0) break;
112 }
113 }
114 scanf("%d",&n);
115 for (int a=1;a<=n;a++)
116 scanf(LL,&z[a]);
117 for (int a=1;a<=n;a++)
118 for (int b=1;b<=cnt;b++)
119 while (z[a]%p[b]==0)
120 z[a]/=p[b],num[b]++;
121 for (int a=1;a<=n;a++)
122 for (int b=a+1;b<=n;b++)
123 if (z[a]!=1 && z[b]!=1 && z[a]!=z[b])
124 {
125 long long g=gcd(z[a],z[b]);
126 if (g!=1)
127 {
128 cnt++;
129 for (int c=1;c<=n;c++)
130 while (z[c]%g==0)
131 z[c]/=g,num[cnt]++;
132 if (z[a]!=1)
133 {
134 g=z[a];
135 cnt++;
136 for (int c=1;c<=n;c++)
137 while (z[c]%g==0)
138 z[c]/=g,num[cnt]++;
139 }
140 if (z[b]!=1)
141 {
142 g=z[b];
143 cnt++;
144 for (int c=1;c<=n;c++)
145 while (z[c]%g==0)
146 z[c]/=g,num[cnt]++;
147 }
148 }
149 }
150 for (int a=1;a<=n;a++)
151 if (z[a]!=1)
152 {
153 long long v=(long long)(sqrt(z[a]));
154 if (v*v==z[a])
155 {
156 cnt++;
157 for (int b=1;b<=n;b++)
158 while (z[b]%v==0)
159 z[b]/=v,num[cnt]++;
160 }
161 }
162 for (int a=1;a<=n;a++)
163 if (prime(z[a]))
164 {
165 cnt++;
166 long long v=z[a];
167 for (int b=1;b<=n;b++)
168 while (z[b]%v==0)
169 z[b]/=v,num[cnt]++;
170 }
171 int ans=0,res=0;
172 for (int a=1;a<=cnt;a++)
173 {
174 if (num[a]>ans)
175 {
176 ans=num[a];
177 res=0;
178 }
179 if (num[a]==ans) res++;
180 }
181 for (int a=1;a<=n;a++)
182 if (z[a]!=1)
183 {
184 int nownum=0;
185 for (int b=a;b<=n;b++)
186 if (z[b]==z[a]) nownum++;
187 if (nownum>ans)
188 {
189 ans=nownum;
190 res=0;
191 }
192 if (nownum==ans) res+=2;
193 }
194 printf("%d\n",ans);
195 ans=res;
196 y[1]=1;
197 int l=1;
198 while (ans)
199 {
200 for (int a=1;a<=l;a++)
201 y[a]<<=1;
202 for (int a=1;a<=l;a++)
203 if (y[a]>=10)
204 {
205 y[a]-=10;
206 y[a+1]++;
207 }
208 if (y[l+1]) l++;
209 ans--;
210 }
211 y[1]--;
212 for (int a=l;a>=1;a--)
213 printf("%d",y[a]);
214 printf("\n");
215
216 return 0;
217 }
Intelligence Test:
每次暴力二分找下一个位置。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<vector>
6
7 using namespace std;
8
9 const int maxn=1000010;
10
11 int n,m;
12
13 vector<int> z[maxn];
14
15 int main()
16 {
17 freopen("test.in","r",stdin);
18 freopen("test.out","w",stdout);
19
20 scanf("%d",&n);
21 for (int a=1;a<=n;a++)
22 {
23 int v;
24 scanf("%d",&v);
25 z[v].push_back(a);
26 }
27 scanf("%d",&m);
28 for (int a=1;a<=m;a++)
29 {
30 scanf("%d",&n);
31 int p=0;
32 bool able=true;
33 for (int b=1;b<=n;b++)
34 {
35 int v;
36 scanf("%d",&v);
37 int x=upper_bound(z[v].begin(),z[v].end(),p)-z[v].begin();
38 if (x==(int)z[v].size() || z[v][x]<=p)
39 {
40 able=false;
41 for (int c=b+1;c<=n;c++)
42 scanf("%d",&v);
43 break;
44 }
45 p=z[v][x];
46 }
47 if (able) printf("TAK\n");
48 else printf("NIE\n");
49 }
50
51 return 0;
52 }
Antisymmetry:
只对中间位置做manachar。
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,f[maxn],z[maxn];
11
12 char s[maxn];
13
14 int main()
15 {
16 freopen("antisymmetry.in","r",stdin);
17 freopen("antisymmetry.out","w",stdout);
18
19 scanf("%d",&n);
20 scanf("%s",s+1);
21 for (int a=n;a>=1;a--)
22 z[a*2]=(s[a]=='0' ? 0 : 2);
23 n<<=1;
24 n++;
25 for (int a=1;a<=n;a+=2)
26 z[a]=1;
27 f[1]=1;
28 int nowr=1,nowm=1;
29 for (int a=1;a<=n;a+=2)
30 {
31 if (a<=nowr) f[a]=min(nowr-a+1,f[nowm+nowm-a]);
32 else f[a]=1;
33 while (a+f[a]<n && a-f[a]>0 && z[a+f[a]]+z[a-f[a]]==2)
34 f[a]++;
35 if (a+f[a]-1>=nowr)
36 {
37 nowr=a+f[a]-1;
38 nowm=a;
39 }
40 }
41 long long ans=0;
42 for (int a=1;a<=n;a+=2)
43 ans+=f[a]>>1;
44 printf("%lld\n",ans);
45
46 return 0;
47 }
Hamsters:
矩阵倍增。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<vector>
5
6 using namespace std;
7
8 #define ull unsigned long long
9 #define calc(a,b,c) (h[a][c]-h[a][b-1]*bit[c-b+1])
10
11 const int maxn=210;
12 const int maxl=100010;
13 const ull base=10007;
14
15 int n,m,l[maxn];
16
17 long long m1[maxn],m2[maxn][maxn],m3[maxn],m4[maxn][maxn];
18
19 ull bit[maxl];
20
21 char s[maxl];
22
23 vector<ull> h[maxn];
24
25 int main()
26 {
27 freopen("hamsters.in","r",stdin);
28 freopen("hamsters.out","w",stdout);
29
30 scanf("%d%d",&n,&m);
31 for (int a=1;a<=n;a++)
32 {
33 scanf("%s",s+1);
34 l[a]=strlen(s+1);
35 ull nowv=0;
36 h[a].push_back(nowv);
37 for (int b=1;b<=l[a];b++)
38 {
39 nowv=nowv*base+s[b];
40 h[a].push_back(nowv);
41 }
42 }
43 bit[0]=1;
44 for (int a=1;a<=100000;a++)
45 bit[a]=bit[a-1]*base;
46 for (int a=1;a<=n;a++)
47 for (int b=1;b<=n;b++)
48 {
49 int vx=l[b];
50 for (int c=(l[a]>l[b] ? l[a]-l[b]+2 : 2);c<=l[a];c++)
51 if (calc(a,c,l[a])==calc(b,1,l[a]-c+1))
52 {
53 vx=l[b]-(l[a]-c+1);
54 break;
55 }
56 m2[a][b]=vx;
57 }
58 for (int a=1;a<=n;a++)
59 m1[a]=l[a];
60 m--;
61 while (m)
62 {
63 if (m&1)
64 {
65 memset(m3,0x3f,sizeof(m3));
66 for (int a=1;a<=n;a++)
67 for (int b=1;b<=n;b++)
68 m3[b]=min(m3[b],m1[a]+m2[a][b]);
69 for (int a=1;a<=n;a++)
70 m1[a]=m3[a];
71 }
72 memset(m4,0x3f,sizeof(m4));
73 for (int a=1;a<=n;a++)
74 for (int b=1;b<=n;b++)
75 for (int c=1;c<=n;c++)
76 m4[a][c]=min(m4[a][c],m2[a][b]+m2[b][c]);
77 for (int a=1;a<=n;a++)
78 for (int b=1;b<=n;b++)
79 m2[a][b]=m4[a][b];
80 m>>=1;
81 }
82 for (int a=1;a<=n;a++)
83 m1[1]=min(m1[1],m1[a]);
84 printf("%lld\n",m1[1]);
85
86 return 0;
87 }
Blocks:
首先将所有数都减去K,那么问题就转化成了最长的一段和大于等于0的长度。考虑起点,如果左边有一个比它值小的点就肯定不优,终点亦然。所以用单调队列维护这个序列,然后发现对于起点终点的位置是单调递增的,所以再扫一遍出答案。
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,y[maxn],p1[maxn],p2[maxn];
11
12 long long z[maxn],s1[maxn],s2[maxn];
13
14 int main()
15 {
16 freopen("blocks.in","r",stdin);
17 freopen("blocks.out","w",stdout);
18
19 scanf("%d%d",&n,&m);
20 for (int a=1;a<=n;a++)
21 scanf("%d",&y[a]);
22 for (int a=1;a<=m;a++)
23 {
24 int k;
25 scanf("%d",&k);
26 for (int b=1;b<=n;b++)
27 z[b]=z[b-1]+y[b]-k;
28 int size1=1;
29 s1[1]=0;p1[1]=0;
30 for (int b=1;b<=n;b++)
31 {
32 while (size1 && s1[size1]<z[b])
33 size1--;
34 s1[++size1]=z[b];
35 p1[size1]=b;
36 }
37 int size2=1;
38 s2[1]=z[n];p2[1]=n+1;
39 for (int b=n;b>=0;b--)
40 {
41 while (size2 && s2[size2]>z[b])
42 size2--;
43 s2[++size2]=z[b];
44 p2[size2]=b;
45 }
46 reverse(s2+1,s2+size2+1);
47 reverse(p2+1,p2+size2+1);
48 int ans=0;
49 for (int b=1,c=1;b<=size2;b++)
50 {
51 while (c<=size1 && s1[c]>=s2[b])
52 c++;
53 c--;
54 ans=max(ans,p1[c]-p2[b]);
55 }
56 printf("%d",ans);
57 if (a==m) printf("\n");
58 else printf(" ");
59 }
60
61 return 0;
62 }
Sheep:
一条对角线如果在一开始可行那么它将是一直可行的,所以我们预处理出所有合法的对角线。处理的方法是枚举一个起点然后用极角排序判断即可。最后再用一次DP做出答案即可。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6
7 using namespace std;
8
9 const int maxn=610;
10 const int maxm=20010;
11 const double pi=acos(-1.0);
12 const double eps=1e-10;
13
14 int n,m,mo,f[maxn][maxn];
15
16 bool g[maxn][maxn],con[maxn][maxn];
17
18 struct rec
19 {
20 double arc;
21 int opt;
22 bool operator<(const rec &a)const
23 {
24 return arc<a.arc;
25 }
26 }x[maxn+maxm];
27
28 struct point
29 {
30 int x,y;
31 void init()
32 {
33 scanf("%d%d",&x,&y);
34 }
35 }z[maxn],y[maxm];
36
37 int cross(point a,point b,point c)
38 {
39 return (a.x-b.x)*(a.y-c.y)-(a.y-b.y)*(a.x-c.x);
40 }
41
42 int sgn(double v)
43 {
44 if (fabs(v)<=eps) return 0;
45 if (v>0) return 1;
46 else return -1;
47 }
48
49 bool check(int a,int b)
50 {
51 int cnt1=0,cnt2=0;
52 for (int c=1;c<=m;c++)
53 {
54 int v=cross(z[a],z[b],y[c]);
55 if (v==0) return false;
56 if (v>0) cnt1++;
57 else cnt2++;
58 }
59 return cnt1%2==0 && cnt2%2==0;
60 }
61
62 int solve(int l,int r)
63 {
64 if (g[l][r]) return f[l][r];
65 g[l][r]=true;
66 int &ans=f[l][r];
67 ans=0;
68 if (l+1>=r) return ans=1;
69 if (l+2==r) return ans=con[l][r];
70 for (int a=l+1;a<r;a++)
71 if (con[l][a] && con[r][a])
72 {
73 ans+=(long long)solve(l,a)*solve(a,r)%mo;
74 ans%=mo;
75 }
76 return ans;
77 }
78
79 int main()
80 {
81 freopen("sheep.in","r",stdin);
82 freopen("sheep.out","w",stdout);
83
84 scanf("%d%d%d",&n,&m,&mo);
85 for (int a=1;a<=n;a++)
86 z[a].init();
87 for (int a=1;a<=m;a++)
88 y[a].init();
89 z[n+1]=z[1];
90 z[0]=z[n];
91 for (int a=1;a<=n;a++)
92 {
93 double v=max(atan2(z[a+1].y-z[a].y,z[a+1].x-z[a].x),atan2(z[a-1].y-z[a].y,z[a-1].x-z[a].x));
94 int cnt=0;
95 for (int b=1;b<=n;b++)
96 if (b!=a)
97 {
98 cnt++;
99 x[cnt].opt=b;
100 x[cnt].arc=atan2(z[b].y-z[a].y,z[b].x-z[a].x);
101 if (sgn(x[cnt].arc-v)>0) x[cnt].arc-=2*pi;
102 }
103 for (int b=1;b<=m;b++)
104 {
105 cnt++;
106 x[cnt].opt=0;
107 x[cnt].arc=atan2(y[b].y-z[a].y,y[b].x-z[a].x);
108 if (sgn(x[cnt].arc-v)>0) x[cnt].arc-=2*pi;
109 }
110 sort(x+1,x+cnt+1);
111 int cx=0;
112 x[0].arc=-100;x[cnt+1].arc=100;
113 for (int b=1;b<=cnt;b++)
114 if (x[b].opt)
115 {
116 if (sgn(x[b].arc-x[b-1].arc)==0 || sgn(x[b].arc-x[b+1].arc)==0) ;
117 else
118 {
119 if (cx%2==0) con[a][x[b].opt]=true;
120 }
121 }
122 else cx++;
123 }
124 int ans=0;
125 for (int a=2;a<=n;a++)
126 if (con[n][a] && con[1][a])
127 {
128 ans+=(long long)solve(1,a)*solve(a,n)%mo;
129 ans%=mo;
130 }
131 printf("%d\n",ans);
132
133 return 0;
134 }
The Minima Game:
DP,扫一遍出解。
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,z[maxn];
11
12 int main()
13 {
14 freopen("minima.in","r",stdin);
15 freopen("minima.out","w",stdout);
16
17 scanf("%d",&n);
18 for (int a=1;a<=n;a++)
19 scanf("%d",&z[a]);
20 sort(z+1,z+n+1);
21 int ans=z[1];
22 for (int a=2;a<=n;a++)
23 ans=max(ans,z[a]-ans);
24 printf("%d\n",ans);
25
26 return 0;
27 }
Frog:
扫一遍后倍增。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4
5 using namespace std;
6
7 #define dis(a,b) z[a]-z[b]
8
9 const int maxn=1000010;
10 const long long INF=0x3f3f3f3f3f3f3f3fll;
11
12 int n,k,to[maxn][2],res[maxn];
13
14 long long m,z[maxn];
15
16 int main()
17 {
18 freopen("frog.in","r",stdin);
19 freopen("frog.out","w",stdout);
20
21 scanf("%d%d%lld",&n,&k,&m);
22 for (int a=1;a<=n;a++)
23 scanf("%lld",&z[a]);
24 int front1=1,tail1=-1;
25 int front2=1,tail2=1;
26 for (int a=1;a<=n;a++)
27 {
28 tail1++;
29 front2++;
30 int size=tail1-front1+1+tail2-front2+1;
31 while (true)
32 {
33 if (size<k)
34 {
35 long long disl,disr;
36 if (front1>1) disl=dis(a,front1-1);
37 else disl=INF;
38 if (tail2<n) disr=dis(tail2+1,a);
39 else disr=INF;
40 if (disl<=disr) front1--;
41 else tail2++;
42 size++;
43 }
44 else
45 {
46 long long disl,disr;
47 if (front1>1) disl=dis(a,front1-1);
48 else disl=INF;
49 if (tail2<n) disr=dis(tail2+1,a);
50 else disr=INF;
51 if (disl<=dis(tail2,a) && front2<=tail2) front1--,tail2--;
52 else
53 {
54 if (disr<dis(a,front1) && front1<=tail1) front1++,tail2++;
55 else break;
56 }
57 }
58 }
59 if (front1<=tail1 && dis(a,front1)>=dis(tail2,a)) to[a][0]=front1;
60 else to[a][0]=tail2;
61 }
62 for (int a=1;a<=n;a++)
63 res[a]=a;
64 while (m)
65 {
66 if (m&1)
67 {
68 for (int a=1;a<=n;a++)
69 res[a]=to[res[a]][0];
70 }
71 m>>=1;
72 for (int a=1;a<=n;a++)
73 to[a][1]=to[to[a][0]][0];
74 for (int a=1;a<=n;a++)
75 to[a][0]=to[a][1];
76 }
77 for (int a=1;a<=n;a++)
78 {
79 printf("%d",res[a]);
80 if (a==n) printf("\n");
81 else printf(" ");
82 }
83
84 return 0;
85 }
Bridges:
二分答案后混合图欧拉回路。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5
6 using namespace std;
7
8 const int maxn=1010;
9 const int maxm=2010;
10 const int INF=0x3f3f3f3f;
11
12 int n,m,en,size,in[maxn],out[maxn],s[maxm],t[maxm],v1[maxm],v2[maxm],depth[maxn],q[maxn],res[maxm];
13
14 struct edge
15 {
16 int e,f,id;
17 bool use;
18 edge *next,*op;
19 }*v[maxn],*vx[maxn],ed[(maxm+maxn+maxn)<<1];
20
21 void add_edge(int s,int e,int f,int id)
22 {
23 en++;
24 ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->f=f;v[s]->id=id;
25 en++;
26 ed[en].next=v[e];v[e]=ed+en;v[e]->e=s;v[e]->f=0;v[e]->id=id;
27 v[s]->op=v[e];v[e]->op=v[s];
28 }
29
30 void add_edge(int s,int e,int id)
31 {
32 en++;
33 ed[en].next=vx[s];vx[s]=ed+en;vx[s]->e=e;vx[s]->use=false;vx[s]->id=id;
34 }
35
36 bool bfs()
37 {
38 memset(depth,0,sizeof(depth));
39 depth[0]=1;
40 int front=1,tail=1;
41 q[1]=0;
42 for (;front<=tail;)
43 {
44 int now=q[front++];
45 for (edge *e=v[now];e;e=e->next)
46 if (!depth[e->e] && e->f)
47 {
48 depth[e->e]=depth[now]+1;
49 if (e->e==n+1) return true;
50 q[++tail]=e->e;
51 }
52 }
53 return false;
54 }
55
56 int dfs(int now,int cur_flow)
57 {
58 if (now==n+1) return cur_flow;
59 int rest=cur_flow;
60 for (edge *e=v[now];e && rest;e=e->next)
61 if (e->f && depth[e->e]==depth[now]+1)
62 {
63 int new_flow=dfs(e->e,min(rest,e->f));
64 e->f-=new_flow;
65 e->op->f+=new_flow;
66 rest-=new_flow;
67 }
68 if (cur_flow==rest) depth[now]=-1;
69 return cur_flow-rest;
70 }
71
72 int dinic()
73 {
74 int ans=0;
75 while (bfs())
76 ans+=dfs(0,INF);
77 return ans;
78 }
79
80 bool check(int upper,int opt)
81 {
82 en=0;
83 memset(v,0,sizeof(v));
84 memset(in,0,sizeof(in));
85 memset(out,0,sizeof(out));
86 for (int a=1;a<=m;a++)
87 {
88 if (v1[a]<=upper) out[s[a]]++,in[t[a]]++;
89 if (v2[a]<=upper) add_edge(s[a],t[a],1,a);
90 }
91 for (int a=1;a<=n;a++)
92 if (abs(in[a]-out[a])&1) return false;
93 int sum=0;
94 for (int a=1;a<=n;a++)
95 {
96 int delta=in[a]-out[a];
97 sum+=(delta > 0 ? (delta>>1) : 0);
98 if (delta>0) add_edge(a,n+1,delta>>1,0);
99 if (delta<0) add_edge(0,a,(-delta)>>1,0);
100 }
101 int flow=dinic();
102 if (sum!=flow) return false;
103 if (opt)
104 {
105 for (int a=1;a<=n;a++)
106 for (edge *e=v[a];e;e=e->next)
107 if (e->e!=0 && e->e!=n+1 && e->f) add_edge(a,e->e,e->id);
108 for (int a=1;a<=m;a++)
109 if (v1[a]<=upper && v2[a]>upper) add_edge(s[a],t[a],a);
110 for (int a=1;a<=n;a++)
111 v[a]=vx[a];
112 }
113 return true;
114 }
115
116 void dfs(int now)
117 {
118 for (edge *e=v[now];e;e=e->next)
119 if (!e->use)
120 {
121 e->use=true;
122 dfs(e->e);
123 res[++size]=e->id;
124 }
125 }
126
127 int main()
128 {
129 freopen("bridges.in","r",stdin);
130 freopen("bridges.out","w",stdout);
131
132 scanf("%d%d",&n,&m);
133 int l=INF,r=-INF;
134 for (int a=1;a<=m;a++)
135 {
136 scanf("%d%d%d%d",&s[a],&t[a],&v1[a],&v2[a]);
137 if (v1[a]>v2[a]) swap(v1[a],v2[a]),swap(s[a],t[a]);
138 l=min(l,v1[a]);
139 r=max(r,v2[a]);
140 }
141 l--;
142 while (l+1!=r)
143 {
144 int m=(l+r)>>1;
145 if (check(m,0)) r=m;
146 else l=m;
147 }
148 if (!check(r,1))
149 {
150 printf("NIE\n");
151 return 0;
152 }
153 printf("%d\n",r);
154 dfs(1);
155 for (int a=m;a>=1;a--)
156 printf("%d ",res[a]);
157 printf("\n");
158
159 return 0;
160 }
Pilots:
单调队列……这玩意儿我居然想了那么久……
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5
6 using namespace std;
7
8 const int maxn=3000010;
9
10 int k,n,q1[maxn][2],q2[maxn][2];
11
12 int main()
13 {
14 freopen("pilots.in","r",stdin);
15 freopen("pilots.out","w",stdout);
16
17 scanf("%d%d",&k,&n);
18 int front1=1,tail1=0,front2=1,tail2=0,ans=1,p=1;
19 for (int a=1;a<=n;a++)
20 {
21 int v;
22 scanf("%d",&v);
23 while (front1<=tail1 && v<q1[tail1][0])
24 tail1--;
25 q1[++tail1][0]=v;q1[tail1][1]=a;
26 while (front2<=tail2 && v>q2[tail2][0])
27 tail2--;
28 q2[++tail2][0]=v;q2[tail2][1]=a;
29 while (abs(q1[front1][0]-q2[front2][0])>k)
30 {
31 p++;
32 while (q1[front1][1]<p)
33 front1++;
34 while (q2[front2][1]<p)
35 front2++;
36 }
37 ans=max(ans,a-p+1);
38 }
39 printf("%d\n",ans);
40
41 return 0;
42 }