• 【树链剖分】【线段树】bzoj2157 旅游


    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define INF 2147483647
    #define N 20001
    #define lson rt<<1,l,m
    #define rson rt<<1|1,m+1,r
    int v[N<<1],first[N],next[N<<1],en,bw[N<<1],dw[N<<1];
    void AddEdge(int U,int V,int W)
    {
    	v[++en]=V;
    	bw[en]=W;
    	next[en]=first[U];
    	first[U]=en;
    }
    int n,fa[N],top[N],tot,dep[N],siz[N],son[N],Num[N],dy[N],m,Map[N];
    void dfs(int U)
    {
    	siz[U]=1;
    	for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U])
    	  {
    	  	dy[(i+1)>>1]=v[i];
    	  	dw[v[i]]=bw[i];
    	  	fa[v[i]]=U;
    	  	dep[v[i]]=dep[U]+1;
    	  	dfs(v[i]);
    	  	siz[U]+=siz[v[i]];
    	  	if(siz[v[i]]>siz[son[U]])
    	  	  son[U]=v[i];
    	  }
    }
    void df2(int U)
    {
    	Num[U]=++tot;
    	Map[tot]=U;
    	if(son[U])
    	  {
    	  	top[son[U]]=top[U];
    	  	df2(son[U]);
    	  }
    	for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&v[i]!=son[U])
    	  {
    	  	top[v[i]]=v[i];
    	  	df2(v[i]);
    	  }
    }
    int sumv[N<<2],maxv[N<<2],minv[N<<2];
    bool rev[N<<2];
    void work(int rt)
    {
    	rev[rt]^=1;
    	sumv[rt]*=(-1);
    	swap(maxv[rt],minv[rt]);
    	maxv[rt]*=(-1);
    	minv[rt]*=(-1);
    }
    void pushdown(int rt)
    {
    	if(rev[rt])
    	  {
    	  	work(rt<<1);
    	  	work(rt<<1|1);
    	  	rev[rt]=0;
    	  }
    }
    void pushup(int rt)
    {
    	sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
    	maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    	minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
    }
    void buildtree(int rt,int l,int r)
    {
    	if(l==r)
    	  {
    	  	sumv[rt]=minv[rt]=maxv[rt]=dw[Map[l]];
    	  	return;
    	  }
    	int m=(l+r>>1);
    	buildtree(lson);
    	buildtree(rson);
    	pushup(rt);
    }
    void update(int p,int v,int rt,int l,int r)
    {
    	if(l==r)
    	  {
    	  	sumv[rt]=minv[rt]=maxv[rt]=v;
    	  	return;
    	  }
    	pushdown(rt);
    	int m=(l+r>>1);
    	if(p<=m) update(p,v,lson);
    	else update(p,v,rson);
    	pushup(rt);
    }
    void reverse(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	  {
    	  	work(rt);
    	  	return;
    	  }
    	int m=(l+r>>1);
    	pushdown(rt);
    	if(ql<=m) reverse(ql,qr,lson);
    	if(m<qr) reverse(ql,qr,rson);
    	pushup(rt);
    }
    void Reverse(int U,int V)
    {
    	while(top[U]!=top[V])
    	  {
    	  	if(dep[top[U]]<dep[top[V]])
    	  	  swap(U,V);
    	  	reverse(Num[top[U]],Num[U],1,1,n);
    	  	U=fa[top[U]];
    	  }
    	if(U!=V)
    	  {
    	  	if(dep[U]>dep[V])
    		  swap(U,V);
    		reverse(Num[U]+1,Num[V],1,1,n);
    	  }
    }
    int qsum(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr) return sumv[rt];
    	int m=(l+r>>1),res=0;
    	pushdown(rt);
    	if(ql<=m) res+=qsum(ql,qr,lson);
    	if(m<qr) res+=qsum(ql,qr,rson);
    	return res;
    }
    int Qsum(int U,int V)
    {
    	int res=0;
    	while(top[U]!=top[V])
    	  {
    	  	if(dep[top[U]]<dep[top[V]])
    	  	  swap(U,V);
    	  	res+=qsum(Num[top[U]],Num[U],1,1,n);
    	  	U=fa[top[U]];
    	  }
    	if(U!=V)
    	  {
    	  	if(dep[U]>dep[V])
    		  swap(U,V);
    		res+=qsum(Num[U]+1,Num[V],1,1,n);
    	  }
    	return res;
    }
    int qmax(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr) return maxv[rt];
    	int m=(l+r>>1),res=-INF;
    	pushdown(rt);
    	if(ql<=m) res=max(res,qmax(ql,qr,lson));
    	if(m<qr) res=max(res,qmax(ql,qr,rson));
    	return res;
    }
    int Qmax(int U,int V)
    {
    	int res=-INF;
    	while(top[U]!=top[V])
    	  {
    	  	if(dep[top[U]]<dep[top[V]])
    	  	  swap(U,V);
    	  	res=max(res,qmax(Num[top[U]],Num[U],1,1,n));
    	  	U=fa[top[U]];
    	  }
    	if(U!=V)
    	  {
    	  	if(dep[U]>dep[V])
    		  swap(U,V);
    		res=max(res,qmax(Num[U]+1,Num[V],1,1,n));
    	  }
    	return res;
    }
    int qmin(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr) return minv[rt];
    	int m=(l+r>>1),res=INF;
    	pushdown(rt);
    	if(ql<=m) res=min(res,qmin(ql,qr,lson));
    	if(m<qr) res=min(res,qmin(ql,qr,rson));
    	return res;
    }
    int Qmin(int U,int V)
    {
    	int res=INF;
    	while(top[U]!=top[V])
    	  {
    	  	if(dep[top[U]]<dep[top[V]])
    	  	  swap(U,V);
    	  	res=min(res,qmin(Num[top[U]],Num[U],1,1,n));
    	  	U=fa[top[U]];
    	  }
    	if(U!=V)
    	  {
    	  	if(dep[U]>dep[V])
    		  swap(U,V);
    		res=min(res,qmin(Num[U]+1,Num[V],1,1,n));
    	  }
    	return res;
    }
    int main()
    {
    	char op[4];
    	int x,y,z;
    	scanf("%d",&n);
    	for(int i=1;i<n;++i)
    	  {
    	  	scanf("%d%d%d",&x,&y,&z);
    	  	AddEdge(x+1,y+1,z);
    	  	AddEdge(y+1,x+1,z);
    	  }
    	top[1]=1;
    	dfs(1);
    	df2(1);
    	buildtree(1,1,n);
    	scanf("%d",&m);
    	for(;m;--m)
    	  {
    	  	scanf("%s%d%d",op,&x,&y);
    	  	if(op[0]=='C') update(Num[dy[x]],y,1,1,n);
    	  	else if(op[0]=='N') Reverse(x+1,y+1);
    	  	else if(op[0]=='S') printf("%d
    ",Qsum(x+1,y+1));
    	  	else if(op[1]=='A') printf("%d
    ",Qmax(x+1,y+1));
    	  	else printf("%d
    ",Qmin(x+1,y+1));
    	  }
    	return 0;
    }
  • 相关阅读:
    ArcGIS学习记录—union、merge及append的区别
    ArcGIS学习记录—属性表的编辑与修改
    ASP.NET应用程序和ASP.NET网站所共有的文件: App_Browsers 等
    C# 文件夹操作
    远程重启服务器
    SQL省市区三级表结构
    c#提出中文首字母
    javascript遍历Json对象个数
    原生javascript添加引用js文件
    简单的div蒙层
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4350995.html
Copyright © 2020-2023  润新知