BZOJ 2157: 旅游【树剖+线段树】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88800029

题目传送门

题目分析:

似乎是个裸题。。
把边权放到深度大的那个点上,查询的时候去掉lca就好了。
然而我虽然知道这一点打的时候仍然把lca加进去了。。

然后就是疯狂复制粘贴再ctrlF替换。。

然而还是WA。。写的时候C操作改点的时候没有用dfs序直接把点编号带了进去。
后来又发现连边的时候连了两条u[i]->v[i]。。。自闭

Code:

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define LL long long
#define maxn 20005
using namespace std;
char cb[1<<15],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
	char c; bool f=0; while(!isdigit(c=getc())) if(c=='-') f=1;
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0'); if(f) a=-a;
}
const int inf = 1<<30;
int n,m,a[maxn],seq[maxn];
int dfn[maxn],tim,fa[maxn],son[maxn],siz[maxn],top[maxn],dep[maxn];
int fir[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],tot;
inline void line(int x,int y,int z){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y,w[tot]=z;}
void dfs1(int u){
	siz[u]=1;
	for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=fa[u]){
		fa[v]=u,dep[v]=dep[u]+1,a[v]=w[i];
		dfs1(v);siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int tp){
	top[u]=tp,seq[dfn[u]=++tim]=a[u];
	if(son[u]) dfs2(son[u],tp);
	for(int i=fir[u];i;i=nxt[i]) if(!dfn[to[i]]) dfs2(to[i],to[i]);
}

struct node{
	int s,mn,mx,rev;
	inline void init(int x){s=mn=mx=x;rev=0;}
	inline void reverse(){
		s=-s;static int tmp;
		tmp=mn,mn=-mx,mx=-tmp;
		rev^=1;
	}
}t[maxn<<2];
void pushdown(int i){
	if(t[i].rev){
		t[i<<1].reverse();
		t[i<<1|1].reverse();
		t[i].rev=0;
	}
}
void upd(int i){
	t[i].s=t[i<<1].s+t[i<<1|1].s;
	t[i].mx=max(t[i<<1].mx,t[i<<1|1].mx);
	t[i].mn=min(t[i<<1].mn,t[i<<1|1].mn);
}
void build(int i,int l,int r){
	if(l==r) {t[i].init(seq[l]);return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
	upd(i);
}
void C(int i,int l,int r,int x,int d){
	if(l==r) {t[i].init(d);return;}
	pushdown(i);
	int mid=(l+r)>>1;
	if(x<=mid) C(i<<1,l,mid,x,d);
	else C(i<<1|1,mid+1,r,x,d);
	upd(i);
}
void inverse(int i,int l,int r,int x,int y){
	if(x<=l&&r<=y) {t[i].reverse();return;}
	pushdown(i);
	int mid=(l+r)>>1;
	if(x<=mid) inverse(i<<1,l,mid,x,y);
	if(y>mid) inverse(i<<1|1,mid+1,r,x,y);
	upd(i);
}
void N(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		inverse(1,1,n,dfn[top[u]],dfn[u]);
		u=fa[top[u]];
	}
	if(u==v) return;
	if(dep[u]<dep[v]) swap(u,v);
	inverse(1,1,n,dfn[v]+1,dfn[u]);
}
int querysum(int i,int l,int r,int x,int y){
	if(x<=l&&r<=y) return t[i].s;
	pushdown(i);
	int mid=(l+r)>>1,ret=0;
	if(x<=mid) ret+=querysum(i<<1,l,mid,x,y);
	if(y>mid) ret+=querysum(i<<1|1,mid+1,r,x,y);
	return ret;
}
int querymax(int i,int l,int r,int x,int y){
	if(x<=l&&r<=y) return t[i].mx;
	pushdown(i);
	int mid=(l+r)>>1,ret=-inf;
	if(x<=mid) ret=max(ret,querymax(i<<1,l,mid,x,y));
	if(y>mid) ret=max(ret,querymax(i<<1|1,mid+1,r,x,y));
	return ret;
}
int querymin(int i,int l,int r,int x,int y){
	if(x<=l&&r<=y) return t[i].mn;
	pushdown(i);
	int mid=(l+r)>>1,ret=inf;
	if(x<=mid) ret=min(ret,querymin(i<<1,l,mid,x,y));
	if(y>mid) ret=min(ret,querymin(i<<1|1,mid+1,r,x,y));
	return ret;
}
int SUM(int u,int v){
	int ret=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ret+=querysum(1,1,n,dfn[top[u]],dfn[u]);
		u=fa[top[u]];
	}
	if(u==v) return ret;
	if(dep[u]<dep[v]) swap(u,v);
	return ret+querysum(1,1,n,dfn[v]+1,dfn[u]);
}
int MAX(int u,int v){
	int ret=-inf;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ret=max(ret,querymax(1,1,n,dfn[top[u]],dfn[u]));
		u=fa[top[u]];
	}
	if(u==v) return ret;
	if(dep[u]<dep[v]) swap(u,v);
	return ret=max(ret,querymax(1,1,n,dfn[v]+1,dfn[u]));
}
int MIN(int u,int v){
	int ret=inf;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ret=min(ret,querymin(1,1,n,dfn[top[u]],dfn[u]));
		u=fa[top[u]];
	}
	if(u==v) return ret;
	if(dep[u]<dep[v]) swap(u,v);
	return ret=min(ret,querymin(1,1,n,dfn[v]+1,dfn[u]));
}
int u[maxn],v[maxn],p[maxn];
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("H.in","r",stdin);
	#endif
	int x,y,z;char op,op2;
	read(n);
	for(int i=1;i<n;i++){
		read(u[i]),read(v[i]),read(z),u[i]++,v[i]++;
		line(u[i],v[i],z),line(v[i],u[i],z);
	}
	dfs1(1),dfs2(1,1);
	for(int i=1;i<n;i++) p[i]=dep[u[i]]>dep[v[i]]?u[i]:v[i];
	build(1,1,n);
	read(m);
	while(m--){
		while(!isalpha(op=getc()));op2=getc();
		read(x),read(y);
		if(op=='C') {C(1,1,n,dfn[p[x]],y);continue;}
		x++,y++;
		if(op=='N') N(x,y);
		if(op=='S') printf("%d\n",SUM(x,y));
		if(op=='M') printf("%d\n",op2=='A'?MAX(x,y):MIN(x,y));
	}
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88800029