zoukankan      html  css  js  c++  java
  • 关于旅游这个题需要注意的小点

    因为这个题细节有些多,所以写了一下注意的点,具体思路的话是个模板
    会树剖的话应该都会写

    #include<iostream>
    #include<cstdio>
    #define l(o) (o<<1)
    #define r(o) (o<<1|1)
    #define mid ((l+r)>>1) 
    using namespace std;
    const int N=2e5+7;
    struct edge{
    	int v,w,nxt;
    }e[N<<1];
    int n,m,cnt;
    int head[N],dep[N],top[N],siz[N],fa[N],minn[N],maxn[N],sum[N],tag[N],hs[N],w[N],dfn[N],a[N],from[N],to[N];
    void add_edge(int u,int v,int w){
    	cnt++;
    	e[cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    void get_tree(int u){
    	dep[u]=dep[fa[u]]+1;
    	siz[u]=1;
    	for(int i=head[u];i;i=e[i].nxt){
    		int to=e[i].v;
    		if(to!=fa[u]){
    			fa[to]=u;
    			get_tree(to);
    			w[to]=e[i].w;
    			siz[u]+=siz[to];
    			if(siz[hs[u]]<siz[to])hs[u]=to;
    		}
    	}
    }
    
    void dfs(int u,int fat){
    	top[u]=fat;
    	dfn[u]=++cnt;
    	a[dfn[u]]=w[u];
    	if(hs[u])dfs(hs[u],fat);
    	for(int i=head[u];i;i=e[i].nxt){
    		int to=e[i].v;
    		if(to!=fa[u]&&to!=hs[u]){
    			dfs(to,to);
    		}
    	}
    }
    
    void up(int o){
    	sum[o]=sum[l(o)]+sum[r(o)];
    	maxn[o]=max(maxn[l(o)],maxn[r(o)]);
    	minn[o]=min(minn[l(o)],minn[r(o)]);
    }
    	
    void build(int o,int l,int r){
    	if(l==r){
    		 sum[o]=maxn[o]=minn[o]=a[l];
    		 return ;
    	}
    	build(l(o),l,mid);build(r(o),mid+1,r);
    	up(o);
    }
    //注意线段树标记的更改,自己本身取反,并把标记取反(注意:标记对自己本身没有影响,有影响的是他的子树); 
    void modify(int o){
    	sum[o]=-sum[o];
    	int t=maxn[o];
    	maxn[o]=-minn[o];
    	minn[o]=-t;
    }
    
    void down(int o,int l,int r){
    	if(tag[o]){
    		tag[l(o)]^=1,tag[r(o)]^=1;
    		modify(l(o));
    		modify(r(o));
    		tag[o]=0;
    	}
    }
    
    void change(int o,int l,int r,int L,int R){
    	if(L<=l&&R>=r){
    		tag[o]^=1;
    		modify(o);
    		return ;
    	}
    	down(o,l,r);
    	if(L<=mid)change(l(o),l,mid,L,R);
    	if(R>mid)change(r(o),mid+1,r,L,R);
    	up(o);
    }
    
    void chenge(int o,int l,int r,int k,int val){
    	if(l==r){
    		sum[o]=maxn[o]=minn[o]=val;
    		return ;
    	}
    	down(o,l,r);
    	if(k<=mid)chenge(l(o),l,mid,k,val);
    	else chenge(r(o),mid+1,r,k,val);
    	up(o);
    }
    
    int ask(int o,int l,int r,int L,int R,int val){
    	if(L<=l&&R>=r){
    		if(val==1)return sum[o];
    		if(val==2)return maxn[o];
    		if(val==3)return minn[o];
    	}
    	down(o,l,r);
    	int res=0;
    	if(val==1){
    		if(L<=mid)res+=ask(l(o),l,mid,L,R,val);
    		if(R>mid)res+=ask(r(o),mid+1,r,L,R,val);
    		return res;
    	}
    	if(val==2){
    		res=-233333333;
    		if(L<=mid)res=max(res,ask(l(o),l,mid,L,R,val));
    		if(R>mid)res=max(res,ask(r(o),mid+1,r,L,R,val));
    		return res;
    	}
    	if(val==3){
    		res=23333333;
    		if(L<=mid)res=min(res,ask(l(o),l,mid,L,R,val));
    		if(R>mid)res=min(res,ask(r(o),mid+1,r,L,R,val));
    		return res;
    	}
    }
    
    void solve(int x,int y,int val){
    	int ans=0;
    	if(val==3) ans=23333333; 
    	if(val==2) ans=-23333333;//注意可能有负边权; 
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		if(val==4){
    			change(1,1,n,dfn[top[x]],dfn[x]);
    		}else{
    			if(val==1)ans+=ask(1,1,n,dfn[top[x]],dfn[x],val);
    			if(val==2)ans=max(ans,ask(1,1,n,dfn[top[x]],dfn[x],val));
    			if(val==3)ans=min(ans,ask(1,1,n,dfn[top[x]],dfn[x],val));
    		}
    		x=fa[top[x]];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	if(val==4)change(1,1,n,dfn[x]+1,dfn[y]);
    	if(val==1)ans+=ask(1,1,n,dfn[x]+1,dfn[y],val);
    	if(val==2)ans=max(ans,ask(1,1,n,dfn[x]+1,dfn[y],val));//注意边转点的题dfn+1; 
    	if(val==3)ans=min(ans,ask(1,1,n,dfn[x]+1,dfn[y],val));//不能在这里赋初值 
    	if(val>=1&&val<=3)cout<<ans<<"
    ";
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		add_edge(x+1,y+1,z);
    		add_edge(y+1,x+1,z);
    		from[i]=x+1;to[i]=y+1;
    	}
    	cnt=0;
    	get_tree(1);
    	dfs(1,1);
    	build(1,1,n);	
    	scanf("%d",&m);
    	
    //	for(int i = 1; i <=n; i ++){
    //		cout<<ask(1,1,n,dfn[i],dfn[i],1)<<"
    ";
    //	}
    	while(m--){
    		char opt[5];
    		int x,y;
    		scanf("%s",opt+1);
    		scanf("%d%d",&x,&y);
    		if(opt[1]=='C'){
    			if(fa[from[x]]==to[x])chenge(1,1,n,dfn[from[x]],y);//注意是dfn,注意这里的x,y不用加1; 
    			else chenge(1,1,n,dfn[to[x]],y);
    			continue;
    		}
    		x+=1;y+=1;//在这里加一; 
    		if(opt[1]=='N'){
    			solve(x,y,4);
    			continue;
    		}
    		if(opt[1]=='S'){
    			//cout<<"1"<<"
    ";
    			solve(x,y,1);
    			continue;
    		}
    		if(opt[2]=='A'){
    			solve(x,y,2);
    			continue;
    		}
    		if(opt[2]=='I'){
    			solve(x,y,3);
    		}
    	}
    }
    
  • 相关阅读:
    LeetCode-198-打家劫舍
    LeetCode-279-完全平方数
    LeetCode-91-解码方法
    Redis RDB 分析工具 rdbtools 说明(转载)
    ftp软件下载,ftp软件到底在哪里下载
    element-ui组件库二次开发——打包、上传npm
    ftp客户端工具,这6款好用的ftp客户端工具,站长们必不可少的常用工具!
    不会用Java Future,我怀疑你泡茶没我快, 又是超长图文!!(转载)
    ftp管理软件,ftp管理软件怎么使用
    Android连载22-自定义广播之标准广播发送(转载)
  • 原文地址:https://www.cnblogs.com/Aswert/p/13408325.html
Copyright © 2011-2022 走看看