一眼树剖题
对每种颜色开一颗线段树,动态开点,记录最大值与和,查询直接查找,修改的话只会修改单点,所以最多增加2logn个节点
(原来把题目看错了,以为修改也是修改连续一段的,似乎这样空间会大很多)
#include
#include
#include
#include
using namespace std;
const int Maxn = 1000005;
int sum[Maxn*10], maxx[Maxn*10];
int Fa[Maxn], fa[Maxn];
int dep[Maxn], T[Maxn];
int size[Maxn], dfn[Maxn];
int L[Maxn], R[Maxn];
int w[Maxn], c[Maxn];
int son[Maxn*10][2];
int n,Q,x,y,id,tim;
char S[10];
vector e[Maxn];
void find_heavy_edge(int x){
dep[x] = dep[fa[x]]+1;
int len = e[x].size();
size[x] = 1;
for (int i=0;i size[b];
}
void link_heavy_edge(int x){
dfn[++tim] = x; L[x] = tim;
sort(e[x].begin(),e[x].end(),cmp);
if (x>1) e[x].erase( e[x].begin() );
else Fa[x] = x;
int len = e[x].size();
for (int i=0;i>1;
if (mid>=pos) insert(son[p][0],l,mid,pos,data);
else insert(son[p][1],mid+1,r,pos,data);
sum[p] = sum[son[p][0]] + sum[son[p][1]];
maxx[p] = max( maxx[son[p][0]], maxx[son[p][1]] );
}
int query_sum(int p,int l,int r,int L,int R){
if (p==0) return 0;
if (L>r || l>R) return 0;
if (L<=l && R>=r) return sum[p];
int mid = (l+r)>>1;
return query_sum(son[p][0],l,mid,L,R) + query_sum(son[p][1],mid+1,r,L,R);
}
int query_max(int p,int l,int r,int L,int R){
if (p==0) return 0;
if (L>r || l>R) return 0;
if (L<=l && R>=r) return maxx[p];
int mid = (l+r)>>1;
return max( query_max(son[p][0],l,mid,L,R), query_max(son[p][1],mid+1,r,L,R) );
}
void work1(){
insert(T[c[x]],1,n,L[x],0);
c[x] = y;
insert(T[c[x]],1,n,L[x],w[x]);
}
void work2(){
w[x] = y;
insert(T[c[x]],1,n,L[x],w[x]);
}
void work3(){
int col = c[x], ans = 0;
while (Fa[x]!=Fa[y])
{
if (dep[Fa[x]]L[y]) swap(x,y);
ans += query_sum(T[col],1,n,L[x],L[y]);
printf("%d\n",ans);
}
void work4(){
int col = c[x], ans = 0;
while (Fa[x]!=Fa[y])
{
if (dep[Fa[x]]L[y]) swap(x,y);
ans = max(ans, query_max(T[col],1,n,L[x],L[y]) );
printf("%d\n",ans);
}
int main(){
scanf("%d%d",&n,&Q);
for (int i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for (int i=1;i