[bzoj 3531]sdoi 2014旅行


一目で問題を切り出す.
色ごとに線分ツリーを開き、動的に点を開き、最大値と和を記録し、クエリーを直接検索します.変更すると単点のみが変更されるので、最大2 lognノードを追加します.
(タイトルを見間違えていたので、修正しても修正が連続していると思っていたのですが、このような空間が大きくなるようです)
#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
",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
",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