zoukankan      html  css  js  c++  java
  • BZOJ2594 [Wc2006]水管局长数据加强版

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ2594

    正解:LCT

    解题报告:

      这道题需要维护动态删边,每次查询两点间的最大边权的最小值。

      显然用LCT维护最小生成时即可,由于是删边,我们转化为倒着加边就可以了,就跟上一道题:魔法森林几乎一模一样了。

      注意这题卡常,对于边的话,可以先sort一遍,依次往里面加,相当于是做了一遍最小生成树,常数小很多。

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    using namespace std;
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    const int MAXN = 1100011;
    const int MAXM = 1000011;
    int n,m,Q,F[100011],father[MAXN],tr[MAXN][2],mx[MAXN],from[MAXN],tiao;
    int tot,tag[MAXN],top,stack[MAXN],a[MAXN],pos,match[MAXN][2],ans[100011];
    bool stop[MAXM];
    
    struct edge{ int x,y,z; }e[MAXM],lin;
    inline bool cmpw(edge TA,edge TAT){ return TA.z<TAT.z; }
    struct ask{ int type,x,y,bel; }q[100011];
    struct node{ int x,id; }tmp;
    inline bool cmp(node TA,node TAT){ return TA.x<TAT.x; }
    vector<node>E[100011];
    
    inline bool isroot(int x){ return (tr[father[x]][0]!=x) && (tr[father[x]][1]!=x); }
    inline int find(int x){ if(F[x]!=x) F[x]=find(F[x]); return F[x]; }
    inline void upd(int x,int y){ if(mx[x]<mx[y]) { mx[x]=mx[y]; from[x]=from[y]; } }
    
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline int find_edge(int x,int y){
    	int l=0,r=E[x].size()-1,mid;
    	while(l<=r) {
    		mid=(l+r)>>1; if(E[x][mid].x==y) return E[x][mid].id;
    		if(E[x][mid].x>y) r=mid-1;
    		else l=mid+1;
    	}
    	return 0;
    }
    
    inline void update(int x){
    	from[x]=x; mx[x]=a[x]; int l=tr[x][0],r=tr[x][1];
    	if(l) upd(x,l);
    	if(r) upd(x,r); 
    }
    
    inline void pushdown(int x){
    	if(tag[x]==0) return ;
    	int l=tr[x][0],r=tr[x][1];
    	tag[x]=0; tag[l]^=1; tag[r]^=1;
    	swap(tr[x][0],tr[x][1]);
    }
    
    inline void rotate(int x){
    	int y,z; y=father[x]; z=father[y];
    	int l,r; l=(tr[y][1]==x); r=l^1;
    	if(!isroot(y)) tr[z][(tr[z][1]==y)]=x;
    	father[x]=z; father[y]=x;
    	tr[y][l]=tr[x][r]; father[tr[x][r]]=y; tr[x][r]=y;
    	update(y); update(x);
    }
    
    inline void splay(int x){
    	top=0; stack[++top]=x; int y,z;
    	for(int i=x;!isroot(i);i=father[i]) stack[++top]=father[i];
    	for(int i=top;i>=1;i--) pushdown(stack[i]);
    	while(!isroot(x)) {
    		y=father[x]; z=father[y];
    		if(!isroot(y)) {
    			if((tr[y][0]==x) ^ (tr[z][0]==y)) rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    }
    
    inline void access(int x){
    	int last=0;
    	while(x) {
    		splay(x); tr[x][1]=last;
    		update(x);//!!!
    		last=x; x=father[x];
    	}
    }
    
    inline void move_to_the_root(int x){
    	access(x);
    	splay(x);
    	tag[x]^=1;
    }
    
    inline void link(int x,int y){
    	move_to_the_root(x);
    	father[x]=y;
    	//splay(x);
    }
    
    inline void cut(int x,int y){
    	move_to_the_root(x);
    	access(y);
    	splay(y);
    	tr[y][0]=father[x]=0;
    	update(y);
    }
    
    inline void build(edge bian){
    	tot++; a[tot]=bian.z; from[tot]=tot; mx[tot]=a[tot];
    	match[tot][0]=bian.x; match[tot][1]=bian.y;
    	link(bian.x,tot);
    	link(bian.y,tot);
    }
    
    inline int query(int x,int y){
    	move_to_the_root(x);
    	access(y); splay(y);
    	pos=from[y]; return mx[y];
    }
    
    inline void work(){
    	n=getint(); m=getint(); Q=getint(); tot=n;
    	int now,bel; for(int i=1;i<=n;i++) F[i]=i;
    	for(int i=1;i<=m;i++) {
    		e[i].x=getint(); e[i].y=getint(); e[i].z=getint();
    		if(e[i].x>e[i].y) swap(e[i].x,e[i].y); 
    	}
    	sort(e+1,e+m+1,cmpw);
    	for(int i=1;i<=m;i++) {
    		tmp.x=e[i].y; tmp.id=i;
    		E[e[i].x].push_back(tmp);
    	}
    	for(int i=1;i<=n;i++) if(E[i].size()>0) sort(E[i].begin(),E[i].end(),cmp);
    	for(int i=1;i<=Q;i++) { 
    		q[i].type=getint(); q[i].x=getint(); q[i].y=getint(); 
    		if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
    		if(q[i].type==2) q[i].bel=find_edge(q[i].x,q[i].y),stop[q[i].bel]=1;
    	}
    	for(int i=1;i<=m;i++) {
    		if(stop[i]) continue;
    		if(find(e[i].x)!=find(e[i].y)) { 
    			build(e[i]);
    			F[find(e[i].x)]=find(e[i].y);
    			continue; 
    		}
    		//now=query(e[i].x,e[i].y);
    		//if(now<=e[i].z) continue;
    		//cut(pos,match[pos][0]);
    		//cut(pos,match[pos][1]);
    		//build(e[i]);
    	}
    	for(int o=Q;o>=1;o--) {
    		if(q[o].type==1) { ans[o]=query(q[o].x,q[o].y); continue; }
    		if(find(q[o].x)!=find(q[o].y)) {
    			now=find_edge(q[o].x,q[o].y);
    			build(e[now]); 
    			F[find(e[now].x)]=find(e[now].y); 
    			continue; 
    		}
    		bel=q[o].bel;
    		now=query(q[o].x,q[o].y);
    		if(now<=e[bel].z) continue;
    		cut(pos,match[pos][0]);
    		cut(pos,match[pos][1]);
    		build(e[bel]);
    	}
    	for(int i=1;i<=Q;i++) if(q[i].type==1) printf("%d
    ",ans[i]);
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    cpu 怎么区分指令与数据,寄存器与内存各自对应什么
    添加省略号
    有关自有属性,原型属性的问题
    实现一个new
    滚动条样式修改
    备忘录实现+具体需求应用备忘录
    Math.random生成指定范围的随机数
    reduce详细用法
    一个搜索上下的功能,用的不多
    svg拖拽rect,line,circle
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6477686.html
Copyright © 2011-2022 走看看