[ZJOI2012]网络 解题报告
2016-03-27 15:44
591 查看
这题还是非常奇怪的,在考试的时候做了这题的弱化版,去了求最值。
这道题要求维护一坨链,显然是可以直接上splay的,所以我考试的时候直接写了splay,结果因为两个bug调了5个小时。
求最值的话,当然也可以直接上splay。。但是那样的话很麻烦,因为没法在端点加点,所以要很复杂的讨论。直接用lct的话就好很多,但是用lct维护一坨链实在是很奇怪。。
而且这题的数据很难生成,tm拍都没法拍。。我实在是懒了,就直接下了数据。我也不想为自己解释。
通过这题我发现我的代码能力急需提高啊。
总结:
①改变一个点的孩子指针前要pushdown它。
②链必须从端点开始dfs才行。
③lct中判断(u,v)是否联通,可以先access(u),再access(v),(或者直接getchain(u,v))然后看lct[u].fa,但是注意有个bug是u==v。
④lct中判断(u,v)是否存在,可以先getchain(u,v),如果存在的话,u就会是v的左儿子且u没有儿子,所以就需要看lct[u].fa!=v和lct[u].ch[1].
这道题要求维护一坨链,显然是可以直接上splay的,所以我考试的时候直接写了splay,结果因为两个bug调了5个小时。
求最值的话,当然也可以直接上splay。。但是那样的话很麻烦,因为没法在端点加点,所以要很复杂的讨论。直接用lct的话就好很多,但是用lct维护一坨链实在是很奇怪。。
而且这题的数据很难生成,tm拍都没法拍。。我实在是懒了,就直接下了数据。我也不想为自己解释。
通过这题我发现我的代码能力急需提高啊。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #include<algorithm> #include<cmath> const int N=1e4+5,M=1e5+5,C=10+5,K=1e5+5; struct LS{ int ch[2],fa; int v,max; bool flag; }lct[N*C]; void out(int node){ printf("%d:ch[0]=%d,ch[1]=%d,fa=%d,v=%d,max=%d\n",node,lct[node].ch[0],lct[node].ch[1],lct[node].fa,lct[node].v,lct[node].max); } void pushup(int node){ lct[node].max=max(lct[node].v,max(lct[lct[node].ch[0]].max,lct[lct[node].ch[1]].max)); } void paint(int node){ if(node){ lct[node].flag^=1; swap(lct[node].ch[0],lct[node].ch[1]); } } void pushdown(int node){ if(lct[node].flag){ //printf("pushdown "); //out(node); paint(lct[node].ch[0]),paint(lct[node].ch[1]); lct[node].flag=0; } } int stack[10005]; void down(int node){ int top=0; for(;node;node=lct[node].fa)stack[top++]=node; while(top--)pushdown(stack[top]); } void rot(int node){ int fa=lct[node].fa; bool dir=lct[fa].ch[1]==node; lct[node].fa=lct[fa].fa; lct[fa].fa=node; lct[lct[node].ch[!dir]].fa=fa; lct[fa].ch[dir]=lct[node].ch[!dir]; lct[node].ch[!dir]=fa; if(lct[lct[node].fa].ch[0]==fa)lct[lct[node].fa].ch[0]=node; else if(lct[lct[node].fa].ch[1]==fa)lct[lct[node].fa].ch[1]=node; pushup(fa); } bool is_top(int node){ return lct[node].fa==0||lct[lct[node].fa].ch[1]!=node&&lct[lct[node].fa].ch[0]!=node; } void splay(int node){ down(node); for(int fa;!is_top(node);rot(node)){ fa=lct[node].fa; if(!is_top(fa)) if((lct[lct[fa].fa].ch[1]==fa)==(lct[fa].ch[1]==node))rot(fa); else rot(node); } } void discon(int node){ splay(node); lct[node].ch[1]=0; } void access(int node){ //printf("---access:%d---\n",node); for(discon(node);lct[node].fa;rot(node)){ //printf("%d\n",node); discon(lct[node].fa); //cout<<lct[node].fa<<".ch[1]="<<node<<endl; lct[lct[node].fa].ch[1]=node; } pushup(node); //out(21),out(22); } void makeroot(int node){ access(node); paint(node); } void getchain(int u,int v){ makeroot(u); access(v); } void link(int from,int to){ //printf("link:(%d->%d)\n",from,to); lct[from].fa=to; } void cut(int from,int to){ //printf("cut:(%d->%d)\n",from,to); lct[from].fa=lct[to].ch[0]=0; pushup(to); } int deg[15][10005]; int n; int cal(int w,int i){ return w*n+i; } void in(int &x){ char c=getchar(); for(;c<'0'||c>'9';c=getchar()); for(x=0;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0'); } int ptr[N*C],next[M<<1],succ[M<<1],etot=1; void addedge(int from,int to){ next[etot]=ptr[from],ptr[from]=etot,succ[etot++]=to; } int q[10005]; void bfs(int node){ int h=0,t=1; q[0]=node; for(;h!=t;++h) for(int i=ptr[q[h]];i;i=next[i]) if(succ[i]!=lct[q[h]].fa){ lct[succ[i]].fa=q[h]; //printf("fa(%d)=%d\n",succ[i],q[h]); q[t++]=succ[i]; } } int main(){ //freopen("bzoj_2816.in","r",stdin); //freopen("bzoj_2816.out","w",stdout); freopen("networkzj.in","r",stdin); freopen("networkzj.out","w",stdout); int m,c,k; in(n),in(m),in(c),in(k); for(int i=1;i<=n;++i){ in(lct[i].v); for(int j=0,k=i;j<c;++j,k+=n)lct[k].v=lct[i].v; } for(int i=n*c;i;--i)lct[i].max=lct[i].v; int u,v,w; for(int i=m;i;--i){ in(u),in(v),in(w); addedge(cal(w,u),cal(w,v)),addedge(cal(w,v),cal(w,u)); ++deg[w][u],++deg[w][v]; } for(int i=n*c;i;--i) if(!lct[i].fa) bfs(i); int opt,x,y,prew; for(;k;--k){ //printf("----%d-----\n",k); in(opt); switch(opt){ case 0: in(x),in(y); for(int i=0;i<c;++i,x+=n){ splay(x); lct[x].v=lct[x].max=y; } break; case 1: in(u),in(v),in(w); for(x=u+n*(c-1),y=v+n*(c-1),prew=c-1;x>0;--prew,x-=n,y-=n){ getchain(x,y); if(lct[x].fa==y&&!lct[x].ch[1])break; } //cout<<x<<" "<<y<<":"<<prew<<endl; if(x<=0)puts("No such edge."); else if(w==prew)puts("Success."); else if(deg[w][u]==2||deg[w][v]==2)puts("Error 1."); else{ getchain(cal(w,u),cal(w,v)); if(lct[cal(w,u)].fa)puts("Error 2."); else{ puts("Success."); cut(x,y); --deg[prew][u],--deg[prew][v]; link(cal(w,u),cal(w,v)); ++deg[w][u],++deg[w][v]; } } break; case 2: in(w),in(u),in(v); getchain(cal(w,u),cal(w,v)); if(u==v||lct[cal(w,u)].fa)printf("%d\n",lct[cal(w,v)].max); else puts("-1"); break; } } }
总结:
①改变一个点的孩子指针前要pushdown它。
②链必须从端点开始dfs才行。
③lct中判断(u,v)是否联通,可以先access(u),再access(v),(或者直接getchain(u,v))然后看lct[u].fa,但是注意有个bug是u==v。
④lct中判断(u,v)是否存在,可以先getchain(u,v),如果存在的话,u就会是v的左儿子且u没有儿子,所以就需要看lct[u].fa!=v和lct[u].ch[1].
相关文章推荐
- Volley框架源码分析
- 淘宝的SEM如何操作及“车神”的由来太原网络营销师揭秘
- layoutSubviews何时调用的问题(原文:http://www.cnblogs.com/pengyingh/articles/2417211.html)
- 2014年 无线网络发射器
- Linux网络配置之二ip、ss、网络相关配置文件
- 网络请求
- TCP/IP初探
- 常见的网络请求错误代码含义
- TCP/IP初探
- 安卓学习----使用okHttp(get方式)---下载图片
- javaweb基础--HTTP协议
- BZOJ1834 [ZJOI2010]network 网络扩容(最小费用最大流)
- java 网络编程
- HTTP协议
- 网络属性
- PHP网络编程
- TCP三次握手四次挥手blog.csdn.net/whuslei
- 机器学习-神经网络-手写字体识别
- Android HTTP必知必会
- TCP/IP协议