标签:gif swa ++ 颜色 sim next first none log
前言:
这次NOIP好像考不好就退役?
所以写点日记记录生活 好过什么都没留下 给以后做点怀念
2017.9.5
This Problem Is Too Simple! |
这个超好的题
只要你想到离散化 O(N2logN) 草过是没有什么毛病的
可是你要想到精益求精 所以这样做不好
其实有O(Nlog N)做法
对于每一种颜色的 影响的是以这个点为端点的一条链 然后对于询问x y可以差分出四条链
我们关键是维护一条链怎么办 发现如果这个点+1了 子树内的肯定也+1
那么就是维护一个树状数组 这个点打一个+1标记 这个子树外的第一个点打一个-1标记 然后用树状数组维护前缀和即可
好像常数还没写O(N2logN)好...
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int Maxn=500010;
struct EDGE{int x,y,next;}edge[Maxn]; int len,first[Maxn];
void ins(int x,int y){len++; edge[len].x=x; edge[len].y=y; edge[len].next=first[x]; first[x]=len;}
struct node1
{
int t,op,x,c;
node1(){}
node1(int _t,int _x,int _c,int _op){t=_t; x=_x; c=_c; op=_op;}
}Q1[Maxn*4]; int Q1len=0;
struct node2
{
int t,x,y,c;
node2(){}
node2(int _t,int _x,int _y,int _c){t=_t; x=_x; y=_y; c=_c;}
}Q2[Maxn*4]; int Q2len=0;
int L[Maxn],R[Maxn],id=0; int fa[Maxn][21],dep[Maxn];
void Dfs(int x,int f)
{
L[x]=++id;
for(int k=first[x];k!=-1;k=edge[k].next)
{
int y=edge[k].y; if(y==f) continue;
fa[y][0]=x; dep[y]=dep[x]+1; Dfs(y,x);
}R[x]=id;
}
bool Cmp1(const node1 &x,const node1 &y)
{
if(x.c!=y.c) return x.c<y.c;
return x.t<y.t;
}
bool Cmp2(const node2 &x,const node2 &y)
{
if(x.c!=y.c) return x.c<y.c;
return x.t<y.t;
}
bool Cmp3(const node2 &x,const node2 &y){return x.t<y.t;}
int N,q; int preC[Maxn],C[Maxn],Clen=0; int ans[Maxn];
int tr[Maxn]; int low_bit(int x){return x&(-x);}
void Add(int x,int c){while(x<=N){tr[x]+=c; x+=low_bit(x);}}
int Query(int x){int ans=0; while(x>=1){ans+=tr[x]; x-=low_bit(x);} return ans;}
void Del(int x){while(x<=N){tr[x]=0; x+=low_bit(x);}}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
int deep=dep[x]-dep[y];
for(int i=20;i>=0;i--) if(deep>=(1<<i)) deep-=(1<<i),x=fa[x][i];
if(x==y) return x;
for(int i=20;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
scanf("%d%d",&N,&q);
for(int i=1;i<=N;i++) scanf("%d",&preC[i]),C[++Clen]=preC[i];
for(int i=1;i<=N;i++) Q1[++Q1len]=node1(0,i,preC[i],1);
len=0; memset(first,-1,sizeof(first));
for(int i=1;i<N;i++){int x,y; scanf("%d%d",&x,&y); ins(x,y); ins(y,x);}
id=0; dep[1]=1; Dfs(1,0);
for(int j=1;j<=20;j++) for(int i=1;i<=N;i++) fa[i][j]=fa[fa[i][j-1]][j-1];
for(int i=1;i<=q;i++)
{
char ch; scanf("\n%c",&ch);
if(ch==‘C‘)
{
int x,c; scanf("%d%d",&x,&c); C[++Clen]=c;
if(c!=preC[x])
{
Q1[++Q1len]=node1(i,x,preC[x],-1);
Q1[++Q1len]=node1(i,x,c,1); preC[x]=c;
}
}
else
{
int x,y,c; scanf("%d%d%d",&x,&y,&c);
Q2[++Q2len]=node2(i,x,y,c); C[++Clen]=c;
}
}
sort(Q1+1,Q1+Q1len+1,Cmp1);
sort(Q2+1,Q2+Q2len+1,Cmp2);
sort(C+1,C+Clen+1);
Clen=unique(C+1,C+Clen+1)-(C+1);
int l1=1,l2=1,r1=0,r2=0;
for(int i=1;i<=Clen;i++)
{
int x=C[i];
while(Q1[r1+1].c==C[i] && r1<=Q1len) r1++;
while(Q2[r2+1].c==C[i] && r2<=Q2len) r2++;
int last=l1;
while(l1<=r1 && l2<=r2)
{
if(Q1[l1].t<Q2[l2].t)
{
Add(R[Q1[l1].x]+1,(-1)*Q1[l1].op); Add(L[Q1[l1].x],1*Q1[l1].op);
l1++;
}
else
{
int r=LCA(Q2[l2].x,Q2[l2].y);
ans[Q2[l2].t]=Query(L[Q2[l2].x])+Query(L[Q2[l2].y])-Query(L[r])-Query(L[fa[r][0]]);
l2++;
}
}
while(l1<=r1) l1++;
while(l2<=r2)
{
int r=LCA(Q2[l2].x,Q2[l2].y);
ans[Q2[l2].t]=Query(L[Q2[l2].x])+Query(L[Q2[l2].y])-Query(L[r])-Query(L[fa[r][0]]);
l2++;
}
while(last<=r1) Del(R[Q1[last].x]+1),Del(L[Q1[last].x]),last++;
}
sort(Q2+1,Q2+Q2len+1,Cmp3);
for(int i=1;i<=Q2len;i++) printf("%d\n",ans[Q2[i].t]);
return 0;
}
标签:gif swa ++ 颜色 sim next first none log
原文地址:http://www.cnblogs.com/wohenshuai/p/7481675.html