社区讨论
20pts,求调
P3313[SDOI2014] 旅行参与者 3已保存回复 4
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @m00nxvvv
- 此快照首次捕获于
- 2024/08/19 15:17 2 年前
- 此快照最后确认于
- 2024/08/19 16:52 2 年前
两个小时搞不出来,对题解拷也拷不明白,就是WA。
求助万能的谷民。
CPP#include<bits/stdc++.h>
#define int long long
#define ls tree[pos].l
#define rs tree[pos].r
using namespace std;
const int N = 1e5+10;
const int INF = 0x3f3f3f3f;
struct edge{
int to,nxt;
}e[N<<1];
int n , q , edges , cnt ,a[N],c[N],root[N],tot, rk[N], last[N],father[N],siz[N],dfn[N],top[N],deep[N],son[N];
// root 为每个信仰的线段树的根
struct node{ //动态开点
int sum,maxx,l,r;
}tree[N*15];
void build(int x,int y){
e[++edges] = {y,last[x]};
last[x] = edges;
}
void dfs1(int x,int fa){ //树剖板子
deep[x] = deep[fa] + 1;
father[x] = fa;
siz[x] = 1;
for(int i = last[x]; i; i = e[i].nxt){
int t = e[i].to;
if(t == fa) continue;
dfs1(t,x);
siz[x] += siz[t];
if(siz[t] > siz[son[x]]) son[x] = t;
}
}
void dfs2(int x,int tp){
dfn[x] = ++ cnt;
rk[cnt] = x;
top[x] = tp;
if(son[x]) dfs2(son[x],tp);
for(int i = last[x]; i; i = e[i].nxt){
int t = e[i].to;
if(t == father[x] || t == son[x]) continue;
dfs2(t,t);
}
}
void pushup(int pos){
tree[pos].sum = tree[ls].sum + tree[rs].sum;
tree[pos].maxx = max(tree[ls].maxx , tree[rs].maxx);
}
void update(int &pos,int l,int r,int x, int val){
if(!pos) pos = ++tot;
if(l == r){
tree[pos].sum = tree[pos].maxx = val;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) update(ls,l,mid,x,val);
else update(rs,mid+1,r,x,val);
pushup(pos);
}
void clear(int &pos,int l,int r,int x){ //清除线段树
if(l == r){
tree[pos] = {0,0,0,0},pos = 0;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) clear(ls,l,mid,x);
else clear(rs,mid+1,r,x);
pushup(pos);
if(!ls && !rs) tree[pos] = {0,0,0,0},pos = 0;
}
int querysum(int pos,int l,int r,int x,int y){
if(!pos) return 0;
if(x <= l && r <= y) return tree[pos].sum;
int mid = (l + r) >> 1,res = 0;
if(x <= mid) res += querysum(ls,l,mid,x,y);
if(mid < y) res += querysum(rs,mid+1,r,x,y);
return res;
}
int querymax(int pos,int l,int r,int x,int y){
if(!pos) return 0;
if(x <= l && r <= y) return tree[pos].maxx;
int mid = (l + r) >> 1,res = -INF;
if(x <= mid) res = max(res,querymax(ls,l,mid,x,y));
if(mid < y) res = max(res,querymax(rs,mid+1,r,x,y));
return res;
}
void change1(int x,int val){
clear(root[c[x]],1,n,dfn[x]);
c[x] = val;
update(root[c[x]],1,n,dfn[x],a[x]);
}
void change2(int x,int val){
a[x] = val;
update(root[c[x]],1,n,dfn[x],a[x]);
}
int askmax(int x,int y){
int res = 0;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]])swap(x,y);
res = max(res,querymax(root[c[x]],1,n,dfn[top[x]],dfn[x]));
x = father[top[x]];
}
if(deep[x] > deep[y]) swap(x,y);
res = max(res,querymax(root[c[x]],1,n,dfn[x],dfn[y]));
return res;
}
int asksum(int x,int y){
int res = 0;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]])swap(x,y);
res += querysum(root[c[x]],1,n,dfn[top[x]],dfn[x]);
x = father[top[x]];
}
if(deep[x] > deep[y]) swap(x,y);
res += querysum(root[c[x]],1,n,dfn[x],dfn[y]);
return res;
}
signed main(){
scanf("%lld%lld",&n,&q);
for(int i = 1; i <= n; i++)
scanf("%lld%lld",&a[i],&c[i]);
for(int i = 1; i < n; i++){
int x, y;
scanf("%lld%lld",&x,&y);
build(x,y);
build(y,x);
}
dfs1(1,0);
dfs2(1,1);
for(int i = 1; i <= n; i++)
update(root[c[i]],1,n,dfn[i],a[i]);
while(q--){
char s[10];
int x , y, d;
scanf("%s%lld%lld",s,&x,&y);
if(s[0] == 'C' && s[1] == 'C') change1(x,y);
if(s[0] == 'C' && s[1] == 'W') change2(x,y);
if(s[0] == 'Q' && s[1] == 'S') printf("%lld\n",asksum(x,y));
if(s[0] == 'Q' && s[1] == 'M') printf("%lld\n",askmax(x,y));
}
return 0;
}
回复
共 4 条回复,欢迎继续交流。
正在加载回复...