http://acm.hdu.edu.cn/showproblem.php?pid=5957
好想但是难写
先求个生成树 并把多余边记下来 跑个bfs序并用线段树维护
bfs序和dfs序略有不同 对一个节点 遍历一遍其所有子节点并取最小最大值会得到其一级子节点在bfs序中的区间 再跑一遍就会得到二级子节点在bfs序中的区间 依此类推
然后就是恶心的分类讨论 写了一屏都没写完。。索性把所有要操作的区间都存下来 排个序去个重就好了
#include
using namespace std;
typedef long long ll;
#define pb push_back
const int maxn=1e5+10;
const int N=0x3f3f3f3f;
struct node{
int l,r;
};
vector edge[maxn];
queue que;
node pre[100];
ll sum[4*maxn],laz[4*maxn];
int f[maxn],fa[maxn],mp[maxn],lef1[maxn],rgt1[maxn],lef2[maxn],rgt2[maxn];
int n,q,uu,vv,num;
int getf(int p){
if(f[p]==p) return p;
else return f[p]=getf(f[p]);
}
bool unite(int u,int v){
int fu,fv;
fu=getf(u),fv=getf(v);
if(fu!=fv){
f[fv]=fu;
return 1;
}
else return 0;
}
void bfs(){
int i,u,v,cnt;
while(!que.empty()) que.pop();
que.push(1),fa[1]=0;
cnt=0;
while(!que.empty())
{
u=que.front();
que.pop();
mp[u]=++cnt;
for(i=0;im) update(pl,pr,val,m+1,r,2*cur+1);
pushup(cur);
}
ll query(int pl,int pr,int l,int r,int cur){
ll res;
int m;
if(pl<=l&&r<=pr) return sum[cur];
pushdown(l,r,cur);
res=0,m=(l+r)/2;
if(pl<=m) res+=query(pl,pr,l,m,2*cur);
if(pr>m) res+=query(pl,pr,m+1,r,2*cur+1);
return res;
}
bool cmp(node n1,node n2){
return n1.lpre[j].r) pre[++j]=pre[i];
else pre[j].r=max(pre[j].r,pre[i].r);
}
num=j;
}
int main(){
ll d,res;
int t,i,u,v,k;
char op[10];
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++) edge[i].clear();
for(i=1;i<=n;i++) f[i]=i;
for(i=1;i<=n;i++){
scanf("%d%d",&u,&v);
if(unite(u,v)) edge[u].pb(v),edge[v].pb(u);
else uu=u,vv=v;
}
//printf("***%d %d***\n",uu,vv);
bfs();
init();
scanf("%d",&q);
while(q--){
scanf("%s",op);
if(op[0]=='M'){
scanf("%d%d%lld",&u,&k,&d);
if(k==0) update(mp[u],mp[u],d,1,n,1);
else if(k==1){
num=0;
pre[++num].l=mp[fa[u]],pre[num].r=mp[fa[u]];
pre[++num].l=mp[u],pre[num].r=mp[u];
pre[++num].l=lef1[u],pre[num].r=rgt1[u];
if(u==uu) pre[++num].l=mp[vv],pre[num].r=mp[vv];
else if(u==vv) pre[++num].l=mp[uu],pre[num].r=mp[uu];
solve();
//for(i=1;i<=num;i++) printf("*%d %d*\n",pre[i].l,pre[i].r);
for(i=1;i<=num;i++) update(pre[i].l,pre[i].r,d,1,n,1);
}
else{
num=0;
pre[++num].l=mp[fa[fa[u]]],pre[num].r=mp[fa[fa[u]]];
pre[++num].l=mp[fa[u]],pre[num].r=mp[fa[u]];
pre[++num].l=lef1[fa[u]],pre[num].r=rgt1[fa[u]];
pre[++num].l=mp[u],pre[num].r=mp[u];
pre[++num].l=lef1[u],pre[num].r=rgt1[u];
pre[++num].l=lef2[u],pre[num].r=rgt2[u];
if(fa[u]==uu||fa[u]==vv||(lef1[u]<=mp[uu]&&mp[uu]<=rgt1[u])||(lef1[u]<=mp[vv]&&mp[vv]<=rgt1[u])){
if(fa[u]==vv||(lef1[u]<=mp[vv]&&mp[vv]<=rgt1[u])) swap(uu,vv);
pre[++num].l=mp[vv],pre[num].r=mp[vv];
}
else if(u==uu||u==vv){
if(u==vv) swap(uu,vv);
pre[++num].l=mp[fa[vv]],pre[num].r=mp[fa[vv]];
pre[++num].l=mp[vv],pre[num].r=mp[vv];
pre[++num].l=lef1[vv],pre[num].r=rgt1[vv];
}
solve();
//for(i=1;i<=num;i++) printf("*%d %d*\n",pre[i].l,pre[i].r);
for(i=1;i<=num;i++) update(pre[i].l,pre[i].r,d,1,n,1);
}
}
else{
scanf("%d%d",&u,&k);
if(k==0) res=query(mp[u],mp[u],1,n,1);
else if(k==1){
num=0;
pre[++num].l=mp[fa[u]],pre[num].r=mp[fa[u]];
pre[++num].l=mp[u],pre[num].r=mp[u];
pre[++num].l=lef1[u],pre[num].r=rgt1[u];
if(u==uu) pre[++num].l=mp[vv],pre[num].r=mp[vv];
else if(u==vv) pre[++num].l=mp[uu],pre[num].r=mp[uu];
solve();
res=0;
//for(i=1;i<=num;i++) printf("*%d %d*\n",pre[i].l,pre[i].r);
for(i=1;i<=num;i++) res+=query(pre[i].l,pre[i].r,1,n,1);
}
else{
num=0;
pre[++num].l=mp[fa[fa[u]]],pre[num].r=mp[fa[fa[u]]];
pre[++num].l=mp[fa[u]],pre[num].r=mp[fa[u]];
pre[++num].l=lef1[fa[u]],pre[num].r=rgt1[fa[u]];
pre[++num].l=mp[u],pre[num].r=mp[u];
pre[++num].l=lef1[u],pre[num].r=rgt1[u];
pre[++num].l=lef2[u],pre[num].r=rgt2[u];
if(fa[u]==uu||fa[u]==vv||(lef1[u]<=mp[uu]&&mp[uu]<=rgt1[u])||(lef1[u]<=mp[vv]&&mp[vv]<=rgt1[u])){
if(fa[u]==vv||(lef1[u]<=mp[vv]&&mp[vv]<=rgt1[u])) swap(uu,vv);
pre[++num].l=mp[vv],pre[num].r=mp[vv];
}
else if(u==uu||u==vv){
if(u==vv) swap(uu,vv);
pre[++num].l=mp[fa[vv]],pre[num].r=mp[fa[vv]];
pre[++num].l=mp[vv],pre[num].r=mp[vv];
pre[++num].l=lef1[vv],pre[num].r=rgt1[vv];
}
solve();
res=0;
//for(i=1;i<=num;i++) printf("*%d %d*\n",pre[i].l,pre[i].r);
for(i=1;i<=num;i++) res+=query(pre[i].l,pre[i].r,1,n,1);
}
printf("%lld\n",res);
}
}
}
return 0;
}
/*
1
18
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
7 10
7 11
7 12
8 13
8 14
10 15
10 16
12 17
12 18
6 15
10
M 6 1 5
M 6 2 5
M 6 0 5
M 15 1 2
Q 10 2
*/