zoukankan      html  css  js  c++  java
  • BZOJ3083 遥远的国度

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

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

    题目链接:BZOJ3083

    正解:树链剖分+线段树+分类讨论

    解题报告:

      路径修改$+$查询就用链剖资瓷就好了,问题就在于换根操作怎么办。

      我们的做法是不真正的换根,而是选择分类讨论。

      假设每次的询问点为$x$,当前根为$rt$,如果$rt$在$x$子树中,那么实际的子树就是除了含$rt$的这棵$x$的子树之外的所有部分;

      如果$rt$就是$x$,那么子树是全部;

      否则的话$x$的子树不会发生变化。

      分类讨论一下就做完了==

      修改操作用线段树维护,上一个$set$标记就好了。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #define lc root<<1
    #define rc root<<1|1
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define reg(i,x) for(int i=first[x];i;i=next[i])
    using namespace std;
    typedef long long LL;
    const int MAXN = 200011;
    const int MAXM = 200011; 
    int n,m,rt,ecnt,first[MAXN],to[MAXM],nxt[MAXM],deep[MAXN],top[MAXN],size[MAXN],son[MAXN],father[MAXN],id[MAXN],end[MAXN],pre[MAXN],f[MAXN][18],bel[MAXN];
    LL ans,tag[MAXN*3],a[MAXN*3],vv[MAXN];
    bool hav[MAXN*3];//!!!
    inline void link(int x,int y) { nxt[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=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 void pushdown(int root,int l,int r){ 
    	if(!hav[root] || l==r)return ;
    	tag[lc]=tag[rc]=a[lc]=a[rc]=tag[root]; 
    	hav[lc]=hav[rc]=true;
    	hav[root]=false; tag[root]=0; 
    }
    
    inline void build(int root,int l,int r){
    	if(l==r) { a[root]=vv[ pre[l] ]; return ; }
    	int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r);
    	a[root]=min(a[lc],a[rc]);
    }
    
    inline void modify(int root,int l,int r,int ql,int qr,LL val){
    	pushdown(root,l,r); 
    	if(ql<=l && r<=qr) { tag[root]=val; hav[root]=true; a[root]=val; return ; }
    	int mid=(l+r)>>1;
    	if(ql<=mid) modify(lc,l,mid,ql,qr,val);
    	if(qr>mid) modify(rc,mid+1,r,ql,qr,val);
    	a[root]=min(a[lc],a[rc]);
    }
    
    inline LL query(int root,int l,int r,int ql,int qr){
    	pushdown(root,l,r);
    	if(ql<=l && r<=qr) return a[root];
    	int mid=(l+r)>>1;
    	if(ql>mid) return query(rc,mid+1,r,ql,qr);
    	else if(qr<=mid) return query(lc,l,mid,ql,qr);
    	else return min( query(lc,l,mid,ql,qr) , query(rc,mid+1,r,ql,qr) );
    }
    
    inline void dfs(int x,int fa){
    	size[x]=1;
    	for(int i=first[x];i;i=nxt[i]) {
    		int v=to[i]; if(v==fa) continue;
    		deep[v]=deep[x]+1; f[v][0]=x; father[v]=x; dfs(v,x);
    		size[x]+=size[v]; if(size[v]>size[son[x]]) son[x]=v;
    	}
    }
    
    inline void dfs2(int x,int fa){
    	id[x]=++ecnt; pre[ecnt]=x;
    	if(son[x]) { top[son[x]]=top[x]; dfs2(son[x],x); }
    	for(int i=first[x];i;i=nxt[i]) {
    		int v=to[i]; if(v==fa || v==son[x]) continue;
    		top[v]=v; dfs2(v,x);
    	}
    	end[x]=ecnt;
    }
    
    inline void lca(int x,int y,LL z){
    	int f1=top[x],f2=top[y];
    	while(f1!=f2) {
    		if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
    		modify(1,1,n,id[f1],id[x],z);
    		x=father[f1]; f1=top[x];
    	}
    	if(deep[x]<deep[y]) swap(x,y);
    	modify(1,1,n,id[y],id[x],z);
    }
    
    inline int getF(int x,int F){
    	for(int i=bel[deep[x]];i>=0;i--) 
    		if(deep[f[x][i]]>deep[F]) 
    			x=f[x][i];
    	return x;
    }
    
    inline void work(){
    	n=getint(); m=getint(); int x,y,type,pos; LL z;
    	for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); }
    	for(int i=1;i<=n;i++) scanf("%lld",&vv[i]);
    	rt=getint(); 
    	deep[rt]=1; ecnt=0; dfs(rt,0);
    	top[rt]=rt; dfs2(rt,0);
    	for(int i=2;i<=n;i++) bel[i]=bel[i>>1]+1;
    	for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];
    	build(1,1,n);
    	while(m--) {
    		type=getint(); x=getint();
    		if(type==1) rt=x;
    		else if(type==2) {
    			y=getint(); scanf("%lld",&z);
    			lca(x,y,z);
    		}
    		else {
    			if(x==rt) ans=query(1,1,n,1,n);
    			else if(id[x]<=id[rt] && end[rt]<=end[x]){
    				ans=1LL<<60; 
    				pos=getF(rt,x);//!!!
    				if(id[pos]>1) ans=query(1,1,n,1,id[pos]-1);//!!!
    				if(end[pos]<n) ans=min(ans,query(1,1,n,end[pos]+1,n));//!!!
    			}
    			else ans=query(1,1,n,id[x],end[x]);
    			printf("%lld
    ",ans);
    		}
    	}
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("3083.in","r",stdin);
    	freopen("3083.out","w",stdout);
    #endif
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

     make:

    //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);
    
    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;
    }
    
    int main()
    {
        freopen("3083.in","w",stdout);
        srand(time(NULL));
    	int n,m,size,type;
    	n=10; m=10;
    	//n=10000; m=10000;
    	size=10000000;
    	//n=6; m=6;
    	//size=100;
    	printf("%d %d
    ",n,m);
    	for(int i=2;i<=n;i++) printf("%d %d
    ",rand()%(i-1)+1,i);
    	for(int i=1;i<=n;i++) printf("%d ",rand()%size+1);
    	printf("
    %d
    ",rand()%n+1);
    	for(int i=1;i<=m;i++) {
    		type=rand()%3+1; printf("%d ",type);
    		if(type==1) {
    			printf("%d
    ",rand()%n+1);
    		}
    		else if(type==2) {
    			printf("%d %d %d
    ",rand()%n+1,rand()%n+1,rand()%size+1);
    		}
    		else {
    			printf("%d
    ",rand()%n+1);
    		}
    	}
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

     pai:

    //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>
    #include <bitset>
    using namespace std;
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    
    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;
    }
    
    int main()
    {
        int t=0;
    	while(++t) {
    		printf("%d : ",t);
    		system("make.exe");
    		system("3083.exe");
    		system("2.exe");
    		if(system("fc 3083.out 2.out")){ printf("WA
    "); break;  }
    		else printf("AC
    ");
    	}
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

     数据:

     1.in

    10 10
    1 2
    1 3
    1 4
    2 5
    1 6
    4 7
    2 8
    6 9
    7 10
    22411 20657 24240 21525 12974 17337 3717 26377 23217 20558 
    2
    2 5 6 15012
    3 5
    3 9
    3 7
    1 3
    3 10
    3 2
    2 8 1 29431
    1 8
    2 7 6 30507
    

    1.out

    15012
    23217
    3717
    20558
    15012
    

      

    2.in

    6 6
    1 2
    1 3
    1 4
    3 5
    5 6
    38 66 42 98 40 49 
    6
    1 4
    3 5
    3 3
    3 3
    3 5
    3 5
    

      

    2.out

    40
    40
    40
    40
    40
    

      

  • 相关阅读:
    android中正确保存view的状态
    使用AudioTrack播放PCM音频数据(android)
    【录音】Android录音--AudioRecord、MediaRecorder
    (原创)初识cordova(一)
    忽略git中不需要进行版本管理的文件
    GitHub 小试
    通过View.post()获取View的宽高
    org.json.JSONObject的getString和optString使用注意事项
    android---EditText的多行输入框
    【转】我赌5毛你没见过这样的SpannableString
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6811388.html
Copyright © 2011-2022 走看看