您的位置:首页 > 运维架构

XIII Open Cup named after E.V. Pankratiev. GP of Saratov

2016-07-24 20:42 417 查看
A. Box Game

注意到局面总数不超过$50000$,而且每次操作都会改变石子的奇偶性,因此按奇偶可以将状态建成二分图,然后求出最大匹配。

如果状态数是偶数,那么先手必胜,策略就是每次走匹配边,那么对手不能通过匹配边走回来,因此所有匹配边你都能走掉。

如果状态数是奇数,那么如果此时有奇数个石子,也是先手必胜,因为最后对手会遭遇怎么走都会回到以前走过的局面的困境。

选择完先后手之后,每次按匹配边走下去即可。

B. Circle of Stones

首先将环倍长,破环成链,那么剩下的子串要满足相邻字符不同且首尾字符不同。

通过双指针求出每一段极长的子串,满足相邻字符不同,设这一段长度为$len$,从$2$到$len$枚举剩下的串的长度$L$,若该子串长度为$len-L+1$的前后缀不能完全匹配,则说明存在距离为$L-1$的位置不同,也就能充当首尾,Hash判断即可。

时间复杂度$O(n)$。

#include<cstdio>
#include<cstring>
typedef long long ll;
const int N=2000010,D=233,P=1000000009;
int C,n,m,i,j,k,len;char a
,ans
;ll pow
,f
;
inline ll hash(int l,int r){return((f[r]-f[l-1]*pow[r-l+1])%P+P)%P;}
int main(){
for(pow[0]=i=1;i<N;i++)pow[i]=pow[i-1]*D%P;
while(~scanf("%s",a+1)){
n=strlen(a+1);m=n+n;
for(i=1;i<=n;i++)a[i+n]=a[i];
for(i=1;i<=m;i++)f[i]=(f[i-1]*D+a[i])%P;
for(i=0;i<n;i++)ans[i]='0';
for(i=1;i<=m;i=j+1){
for(j=i;j<m&&a[j]!=a[j+1];j++);
len=j-i+1;
for(k=2;k<=len&&k<=n;k++)if(hash(i,i+len-k)!=hash(j-len+k,j))ans[n-k]='1';
}
for(printf("Case %d: ",++C),i=0;i<n-1;i++)putchar(ans[i]);puts("1");
}
return 0;
}


  

C. Expression with Sets

留坑。

D. Heating System

留坑。

E. Islands

留坑。

F. Longest Two Graphs Common String

设$f[i][j][0]$表示选出的路径里,第一张图中最后一个点是$i$,第二张图中最后一个点是$j$的最大长度。

设$f[i][j][1]$表示选出的路径里,第一张图中最后一个点再往后乱走一步到了$i$,第二张图中最后一个点是$j$的最大长度。

则对于$f[i][j][0]$,只需要枚举指向$j$的边,用$f[i][j'][1]$转移;对于$f[i][j][1]$,只需要枚举指向$i$的边,用$f[i'][j][0]$转移。

时间复杂度$O(n(n+m))$。

#include<cstdio>
const int N=505,M=4010;
int T,n1,n2,m,i,j,k,flag,ans,X,Y,q[N*N][2];
int f

[2],pre

[2];
bool v

[2],vis

[2];
struct G{
int n,g
,v[M],nxt[M],ed;
int i,x,y;
char a
;
void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void init(int _n,int m){
n=_n;
scanf("%s",a+1);
for(ed=0,i=1;i<=n;i++)g[i]=0;
while(m--)scanf("%d%d",&x,&y),add(y,x);
}
}G1,G2;
void dp(int x,int y,int z){
if(vis[x][y][z])flag=1;
if(flag)return;
if(v[x][y][z])return;
vis[x][y][z]=v[x][y][z]=1;
int&t=f[x][y][z],&p=pre[x][y][z];
t=-1,p=0;
if(z==0){
if(G1.a[x]==G2.a[y]){
t=0;
for(int i=G2.g[y];i;i=G2.nxt[i]){
int k=G2.v[i];
dp(x,k,z^1);
if(f[x][k][z^1]>t)t=f[x][k][z^1],p=k;
}
if(~t)t++;
}
}else{
for(int i=G1.g[x];i;i=G1.nxt[i]){
int k=G1.v[i];
dp(k,y,z^1);
if(f[k][y][z^1]>t)t=f[k][y][z^1],p=k;
}
}
vis[x][y][z]=0;
}
int main(){
while(~scanf("%d%d",&n1,&m)){
G1.init(n1,m);
scanf("%d%d",&n2,&m);
G2.init(n2,m);
for(i=1;i<=n1;i++)for(j=1;j<=n2;j++)for(k=0;k<2;k++)v[i][j][k]=vis[i][j][k]=0;
ans=flag=0;
for(i=1;i<=n1;i++)for(j=1;j<=n2;j++){
dp(i,j,0);
if(f[i][j][0]>ans)ans=f[i][j][0],X=i,Y=j;
}
printf("Case %d: ",++T);
if(flag)puts("-1");else{
printf("%d\n",ans);
for(i=ans;i;i--){
q[i][0]=X,q[i][1]=Y;
Y=pre[X][Y][0];
X=pre[X][Y][1];
}
for(i=1;i<=ans;i++)printf("%d%c",q[i][0],i<ans?' ':'\n');
for(i=1;i<=ans;i++)printf("%d%c",q[i][1],i<ans?' ':'\n');
}
}
return 0;
}


  

G. Lyndon Words

找规律构造,可以$O(n)$生成字典序下一个,暴力生成出字典序前$r$小的所有串即可。

时间复杂度$O(nr)$。

H. Temperature

状压DP。

时间复杂度$O(n2^n)$。

I. Editor 2

留坑。

J. Tourist Problem

留坑。

K. Ant versus Woodpecker

显然答案就是虚树上度数$>1$的点的深度的最大值,用ETT维护dfs序并支持查询lca即可。

时间复杂度$O((m+\sum k)\log n)$。

#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int N=400010;
int C,n,m,i,x,g
,Nxt
;
int vis
,a
,dfn
,deg
,t,q
;
int id
;
int d
,st
,en
,pre
,nxt
,val
,md
,size
,son
[2],f
,tot,root;
set<int>T;
inline void up(int x){
md[x]=val[x];
size[x]=1;
if(son[x][0]){
if(d[md[son[x][0]]]<d[md[x]])md[x]=md[son[x][0]];
size[x]+=size[son[x][0]];
}
if(son[x][1]){
if(d[md[son[x][1]]]<d[md[x]])md[x]=md[son[x][1]];
size[x]+=size[son[x][1]];
}
}
inline void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;
if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];son[x][w^1]=y;f[y]=x;up(y);
}
inline void splay(int x,int w){
while(f[x]!=w){
int y=f[x];
if(f[y]!=w){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
if(!w)root=x;
up(x);
}
inline int getrank(int x){
splay(x,0);
return size[son[x][0]];
}
inline void addnode(int x,int y){//x father is y
d[x]=d[y]+1;
int z=nxt[st[y]];
splay(st[y],0);
splay(z,root);
son[z][0]=++tot;
val[tot]=x;
f[tot]=z;
st[x]=tot;
id[tot]=x;
son[st[x]][1]=++tot;
f[tot]=st[x];
val[tot]=y;
en[x]=tot;
up(tot);
up(st[x]);
up(z);
up(root);
nxt[root]=st[x];
nxt[st[x]]=en[x];
nxt[en[x]]=z;
pre[z]=en[x];
pre[en[x]]=st[x];
pre[st[x]]=root;
}
void dfsdel(int x){
if(!x)return;
if(id[x])T.insert(id[x]);
dfsdel(son[x][0]);
dfsdel(son[x][1]);
}
inline void delsubtree(int x){
splay(pre[st[x]],0);
splay(nxt[en[x]],root);
int z=son[root][1];
nxt[root]=z;
pre[z]=root;
dfsdel(son[z][0]);
son[z][0]=0;
up(z);
up(root);
}
void show(int x){
if(!x)return;
show(son[x][0]);
printf("%d ",val[x]);
show(son[x][1]);
}
inline int lca(int x,int y){
if(x==y)return x;
if(x==1||y==1)return 1;
if(getrank(st[x])>getrank(st[y]))swap(x,y);
splay(pre[st[x]],0);
splay(nxt[st[y]],root);
return md[son[son[root][1]][0]];
}
int build(int l,int r,int fa){
int mid=(l+r)>>1;
f[mid]=fa;
if(l<mid)son[mid][0]=build(l,mid-1,mid);
if(r>mid)son[mid][1]=build(mid+1,r,mid);
up(mid);
return mid;
}
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
void dfs(int x){
for(int i=g[x];i;i=Nxt[i]){
d[i]=d[x]+1;
st[i]=++tot;
val[tot]=i;
dfs(i);
en[i]=++tot;
val[tot]=x;
}
}
inline int getid(){
int x=*T.begin();
T.erase(x);
return x;
}
int main(){
while(~scanf("%d",&n)){
st[1]=1;
val[1]=1;
tot=1;
for(i=2;i<=n;i++){
scanf("%d",&x);
Nxt[i]=g[x];
g[x]=i;
}
dfs(1);
en[1]=++tot;
val[tot]=1;
for(i=1;i<tot;i++){
pre[i+1]=i;
nxt[i]=i+1;
}
for(i=1;i<=n;i++)id[st[i]]=i;
root=build(1,tot,0);
int mm;
scanf("%d",&mm);
int lim=n+mm;
T.clear();
for(i=n+1;i<=n+mm;i++)T.insert(i);
int last=0;
printf("Case %d:",++C);
while(mm--){
char op[5];
scanf("%s",op);
if(op[0]=='+'){
int x;
scanf("%d",&x);
int y=getid();
x+=last;
addnode(y,x);
}
if(op[0]=='-'){
int x;
scanf("%d",&x);
delsubtree(x);
}
if(op[0]=='?'){
//show(root);puts("");
scanf("%d",&m);
int cnt=1;
a[1]=1;
vis[1]=1;
dfn[1]=getrank(st[1]);
while(m--){
scanf("%d",&x);
if(!vis[x]){
a[++cnt]=x,vis[x]=1;
dfn[x]=getrank(st[x]);
}
}
//for(i=1;i<=cnt;i++)printf("%d ",a[i]);puts("");
sort(a+1,a+cnt+1,cmp);
int now=cnt;
for(i=1;i<cnt;i++)if(!vis[x=lca(a[i],a[i+1])]){
vis[a[++now]=x]=1;
dfn[x]=getrank(st[x]);
}
sort(a+1,a+now+1,cmp);
//for(i=1;i<=now;i++)printf("%d ",a[i]);puts("");
last=-1;
for(q[t=1]=1,i=2;i<=now;q[++t]=a[i++]){
while(lca(a[i],q[t])!=q[t])t--;
deg[q[t]]++;
if(deg[q[t]]>1)last=max(last,d[q[t]]);
//printf("edge %d %d\n",q[t],a[i]);
}
printf(" %d",last);
for(i=1;i<=now;i++)vis[a[i]]=deg[a[i]]=0;
}
}
puts("");
for(i=1;i<=lim;i++)st[i]=en[i]=d[i]=g[i]=0;
for(i=0;i<=tot+1;i++)id[i]=pre[i]=nxt[i]=val[i]=md[i]=size[i]=son[i][0]=son[i][1]=f[i]=0;
tot=root=0;
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: