zoukankan      html  css  js  c++  java
  • 【*篇】SPOJ QTREE 树链剖分

    发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧..
    WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能得28pts..

    重新见到这些失踪的dalao灰常开心, 于是想让自己心情稍微差一点, 就想着把自己昨天写WA的QTREE重构一遍吧..
    于是重构的sb链剖果然挂掉了... 出现了各种各样的漏洞... 忘记各种各样的句子, 然而退化成了暴力小数据也随便过看不出来啊~~~

    但是还是在1h之内调对了_(:з」∠)_ 已经很满意了... 不过交的时候把自己的样例交上去还CE了一次orz...
    就这样吧..

    题目分析: 两种操作:

    1. 修改第(i)条边(输入顺序).
    2. 查询两个点(u,v)路径上边权的最大值.

    链剖的话边权不是很好搞, 考虑采用之前学过的一种做法

    连x->y边的时候可以拆成x->z->y的两条边啊,然后把边权放在z就可以了

    这样处理完就变成了裸的单点改区间查, 随便套个线段树水一下就好了(说得轻巧, 你细节死成什么样自己心里没点数么= =

    代码:

    #include <cstdio>
    #include <cstring> 
    const int N=202020;
    inline int gn(int a=0,char c=0,int f=1){
    	for(;(c<'0'||c>'9')&&c!='-';c=getchar());
    	if(c=='-') f=-1,c=getchar();
    	for(;c>='0'&&c<='9';c=getchar()) a=a*10+c-'0'; return a*f;
    }
    inline int max(const int& a,const int& b){
    	return a>b?a:b;
    } 
    struct edge{
    	int to,next;
    }e[N]; int v[N],tot;
    void buildedge(int x,int y){
    	e[++tot].to=y; e[tot].next=v[x]; v[x]=tot;
    	e[++tot].to=x; e[tot].next=v[y]; v[y]=tot;
    }
    int fa[N],ez[N],d[N],sz[N];
    void dfs1(int x){ ez[x]=x; sz[x]=1;
    	for(int i=v[x];i;i=e[i].next){
    		int y=e[i].to;
    		if(fa[x]!=y){
    			fa[y]=x; d[y]=d[x]+1; dfs1(y); sz[x]+=sz[y];
    			if(ez[x]==x||sz[y]>sz[ez[x]]) ez[x]=y;
    		}
    	}
    }
    int pos[N],rank[N],tp[N],a[N>>1],ti;
    void dfs2(int x,int tpx){
    	tp[x]=tpx; pos[++ti]=x; rank[x]=ti;
    	if(ez[x]!=x) dfs2(ez[x],tpx);
    	for(int i=v[x];i;i=e[i].next){
    		int y=e[i].to;
    		if(y!=fa[x]&&y!=ez[x]) dfs2(y,y);
    	}
    }
    int t[N<<2],n;
    inline void update(int x){
    	t[x]=max(t[x<<1],t[x<<1|1]);
    }
    void build(int x,int l,int r){
    	if(l==r){
    		t[x]=a[pos[++ti]];
    		return;
    	} int mid=(l+r)>>1;
    	build(x<<1,l,mid);
    	build(x<<1|1,mid+1,r);
    	update(x);
    }
    void change(int x,int l,int r,int k,int s){
    	if(l==r){
    		t[x]=s; return;
    	} int mid=(l+r)>>1;
    	if(k<=mid) change(x<<1,l,mid,k,s);
    	else change(x<<1|1,mid+1,r,k,s);
    	update(x);	
    }
    int query(int x,int l,int r,int L,int R){
    	if(L<=l&&r<=R) return t[x];
    	int mid=(l+r)>>1,ans=-0x7fffffff;
    	if(L<=mid) ans=max(ans,query(x<<1,l,mid,L,R));
    	if(R>mid) ans=max(ans,query(x<<1|1,mid+1,r,L,R));
    	return ans;
    }
    
    inline int querya(int x,int y){ int ans=-0x7fffffff;
    	while(tp[x]!=tp[y])
    		if(d[tp[x]]>d[tp[y]]) ans=max(ans,query(1,1,n,rank[tp[x]],rank[x])),x=fa[tp[x]];
    		else ans=max(ans,query(1,1,n,rank[tp[y]],rank[y])),y=fa[tp[y]];
    	if(d[x]<d[y]) ans=max(ans,query(1,1,n,rank[x],rank[y]));
    	else ans=max(ans,query(1,1,n,rank[y],rank[x]));
    	return ans;
    }
    
    inline void init(){
    	memset(a,192,sizeof(a));
    	memset(v,0,sizeof(v));
    	ti=tot=0;
    }
    inline void work(){ init();
    	n=gn(); int nn=n; n=n*2-1;
    	for(int i=1;i<nn;++i){
    		int x=gn(),y=gn(),z=gn(); a[nn+i]=z;
    		buildedge(x,nn+i); buildedge(nn+i,y);
    	}
    	dfs1(1); dfs2(1,1); fa[1]=1;
    	ti=0; build(1,1,n);
    	char c[10];
    	while(1){
    		scanf("%s",c); if(c[0]=='D') break;
    		int x=gn(),y=gn();
    		if(c[0]=='Q') printf("%d
    ",querya(x,y));
    		else change(1,1,n,rank[nn+x],y);
    	}
    }
    int main(){
    	int T=gn();
    	while(T--)work();
    }
    
  • 相关阅读:
    20145337实验五Java网络编程及安全
    20145337 《Java程序设计》第10周学习总结
    20145337实验四Android开发基础
    20145337 《Java程序设计》第九周学习总结
    20145337实验三实验报告——敏捷开发与XP实践
    20145337《Java程序设计》第八周学习总结
    20145337《JAVA程序设计》第七周学习总结
    JAVA面向对象程序设计——实验报告
    20145337 《Java程序设计》第六周学习总结
    20145336张子扬 《信息安全系统设计基础》第6周学习总结(一)
  • 原文地址:https://www.cnblogs.com/enzymii/p/8442597.html
Copyright © 2011-2022 走看看