poj 3237ツリーチェーン分割
5601 ワード
前の1篇のあの問題に比べて1種の反対数を取る操作が多くて、直接その問題のコードの上で変えて、ここで線分の木の上の各ノードは同時に最大値と最小値を記録して、反対の操作に出会って最大値の反対数は最小値になって、最小値の反対数は最大値になって、中間はlazyとpushdownを利用して、それから差は多くありません.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 1<<29
using namespace std;
struct edge
{
int from,to,val;
};
struct node
{
int l,r,mx,mn,ne;
} t[41111];
vector<edge>edges;
vector<int>g[11111];
int n,a,b,c,sz;
int f[11111],top[11111],w[11111],s[11111];
int dep[11111],son[11111];
char str[21];
void init()
{
sz=0;
edges.clear();
for(int i=1; i<=n; i++)g[i].clear();
}
void add(int from,int to,int val)
{
edges.push_back((edge)
{
from,to,val
});
g[from].push_back(edges.size()-1);
}
void dfs1(int u,int ff)
{
f[u]=ff;
s[u]=1;
son[u]=0;
int size=g[u].size();
for(int i=0; i<size; i++)
{
edge e=edges[g[u][i]];
if(e.to==ff)continue;
dep[e.to]=dep[u]+1;
dfs1(e.to,u);
s[u]+=s[e.to];
if(!son[u]||s[e.to]>s[son[u]])son[u]=e.to;
}
}
void dfs2(int u,int ff,int r)
{
top[u]=ff;
w[u]=++sz;
if(son[u])dfs2(son[u],ff,u);
int size=g[u].size();
for(int i=0; i<size; i++)
{
edge e=edges[g[u][i]];
if(e.to==r||e.to==son[u])continue;
dfs2(e.to,e.to,u);
}
}
void build(int ll,int rr,int rot)
{
t[rot].l=ll;
t[rot].r=rr;
t[rot].mx=-maxn;
t[rot].mn=maxn;
t[rot].ne=0;
if(ll==rr)return;
int mid=(ll+rr)/2;
build(ll,mid,rot<<1);
build(mid+1,rr,rot<<1|1);
}
void pushdown(int rot)
{
t[rot].ne^=1;
t[rot<<1].ne^=1;
t[rot<<1|1].ne^=1;
int u,v;
u=t[rot<<1].mx;
v=t[rot<<1].mn;
t[rot<<1].mx=-v;
t[rot<<1].mn=-u;
u=t[rot<<1|1].mx;
v=t[rot<<1|1].mn;
t[rot<<1|1].mx=-v;
t[rot<<1|1].mn=-u;
}
void update(int x,int vv,int rot)
{
if(t[rot].l==x&&t[rot].r==x)
{
t[rot].mx=vv;
t[rot].mn=vv;
return;
}
if(t[rot].ne)pushdown(rot);
int mid=(t[rot].l+t[rot].r)/2;
if(mid>=x)update(x,vv,rot<<1);
else if(x>mid)update(x,vv,rot<<1|1);
t[rot].mx=max(t[rot<<1].mx,t[rot<<1|1].mx);
t[rot].mn=min(t[rot<<1].mn,t[rot<<1|1].mn);
}
int query(int ll,int rr,int rot)
{
if(ll>rr)return -maxn;
if(t[rot].l==ll&&t[rot].r==rr)return t[rot].mx;
if(t[rot].ne)pushdown(rot);
int mid=(t[rot].l+t[rot].r)/2;
if(rr<=mid)return query(ll,rr,rot<<1);
else if(ll>mid)return query(ll,rr,rot<<1|1);
else return max(query(ll,mid,rot<<1),query(mid+1,rr,rot<<1|1));
}
int solve(int u,int v)
{
int ans=-maxn;
int uu=top[u];
int vv=top[v];
while(uu!=vv)
{
if(dep[uu]>dep[vv])
{
swap(u,v);
swap(uu,vv);
}
ans=max(ans,query(w[vv],w[v],1));
v=f[vv];
vv=top[v];
}
if(dep[u]>dep[v])swap(u,v);
ans=max(ans,query(w[son[u]],w[v],1));
return ans;
}
void update2(int ll,int rr,int rot)
{
if(ll>rr)return;
if(t[rot].l==ll&&t[rot].r==rr)
{
t[rot].ne^=1;
int u,v;
u=t[rot].mx;
v=t[rot].mn;
t[rot].mx=-v;
t[rot].mn=-u;
return;
}
if(t[rot].ne)pushdown(rot);
int mid=(t[rot].l+t[rot].r)/2;
if(rr<=mid)update2(ll,rr,rot<<1);
else if(ll>mid)update2(ll,rr,rot<<1|1);
else
{
update2(ll,mid,rot<<1);
update2(mid+1,rr,rot<<1|1);
}
t[rot].mx=max(t[rot<<1].mx,t[rot<<1|1].mx);
t[rot].mn=min(t[rot<<1].mn,t[rot<<1|1].mn);
}
void negete(int u,int v)
{
int uu=top[u];
int vv=top[v];
while(uu!=vv)
{
if(dep[uu]>dep[vv])
{
swap(u,v);
swap(uu,vv);
}
update2(w[vv],w[v],1);
//ans=max(ans,query(w[vv],w[v],1));
v=f[vv];
vv=top[v];
}
if(dep[u]>dep[v])swap(u,v);
update2(w[son[u]],w[v],1);
//ans=max(ans,query(w[son[u]],w[v],1));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=1; i<n; i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dep[1]=0;
dfs1(1,1);
dfs2(1,1,1);
build(1,sz,1);
int size=edges.size();
for(int i=0; i<size; i+=2)
{
edge e=edges[i];
if(dep[e.from]>dep[e.to])e=edges[i^1];
update(w[e.to],e.val,1);
}
while(scanf("%s",str))
{
if(str[0]=='D')break;
else if(str[0]=='C')
{
scanf("%d%d",&a,&c);
int en=(a-1)*2;
edge e=edges[en];
if(dep[e.from]>dep[e.to])e=edges[en^1];
update(w[e.to],c,1);
}
else if(str[0]=='N')
{
scanf("%d%d",&a,&b);
negete(a,b);
}
else
{
scanf("%d%d",&a,&b);
printf("%d
",solve(a,b));
}
}
}
return 0;
}
/*
1
3
1 2 1
1 3 2
QUERY 1 2
QUERY 1 3
QUERY 2 3
NEGATE 2 3
QUERY 2 3
DONE
*/