HYSBZ - 4999 This Problem Is Too Simple! (主席树)

4999: This Problem Is Too Simple!

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 459   Solved: 204
[ Submit][ Status][ Discuss]

Description

给您一颗树,每个节点有个初始值。
现在支持以下两种操作:
1. C i x(0<=x<2^31) 表示将i节点的值改为x。
2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。

Input

第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。
下面一行N个整数,表示初始时每个节点的初始值。
接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。
接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。

Output

对于每个Q输出单独一行表示所求的答案。

Sample Input

5 6
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 3 40
C 1 40
Q 2 3 40
Q 4 5 30
C 3 10
Q 4 5 30

Sample Output

0
1
1
0

HINT

Source

鸣谢佚名上传




解题思路:正常做法为树链剖分+线段树,每个数字都建一棵线段树,但是这样会爆空间和时间,所以我们动态开点就好了。重新练习了一波动态开点建树。


#include
using namespace std;
typedef long long ll;
const int MAXN=100100;
struct Edge
{
        int to;
        int next;
}e[MAXN*2];
int head[MAXN],edge_num;
void insert_edge(int u,int v)
{
        e[edge_num].to=v;
        e[edge_num].next=head[u];
        head[u]=edge_num++;
}


int top[MAXN];
int fa[MAXN];
int deep[MAXN];
int size[MAXN];
int son[MAXN];
int pos[MAXN];
int SEG;
int A[MAXN];
int N,Q;
void init(){
    edge_num=0;
    memset(head,-1,sizeof(head));
    SEG=1;
    memset(son,-1,sizeof(son));
}

void dfs1(int u,int pre,int d){
        deep[u]=d;
        fa[u]=pre;
        size[u]=1;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            if(v!=pre)
            {
                dfs1(v,u,d+1);
                size[u]+=size[v];
                if(son[u]==-1||size[v]>size[son[u]])
                  son[u]=v;
            }
        }
}

void dfs2(int u,int sp){
    top[u]=sp;
    pos[u]=SEG++;
    if(son[u]!=-1)
      dfs2(son[u],sp);
    else
      return;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].to;
        if(v!=son[u]&&v!=fa[u])
          dfs2(v,v);
    }
}

int root[MAXN<<2],ls[MAXN<<7],rs[MAXN<<7],sum[MAXN<<7];
int col=0,tot=0;

void pushup(int rt){
    sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}

void update(int L,int C,int l,int r,int &rt){
    if(!rt)
      rt=++tot;

    if(l==r){
        sum[rt]+=C;
        return;
    }
    int m=(l+r)/2;
    if(L<=m)
      update(L,C,l,m,ls[rt]);
    else
      update(L,C,m+1,r,rs[rt]);
    pushup(rt);
}

int query(int L,int R,int l,int r,int rt){
    if(!rt)
        return 0;
    if(L<=l&&r<=R)return sum[rt];
    int m=(l+r)/2;
    int ans=0;
    if(L<=m)
        ans+=query(L,R,l,m,ls[rt]);
    if(R>m)
        ans+=query(L,R,m+1,r,rs[rt]);
    return ans;
}

int query(int u,int v,int x){
    int f1=top[u],f2=top[v];
    int temp=0;
    while(f1!=f2){
        if(deep[f1]deep[v])
      swap(u,v);
    temp+=query(pos[u],pos[v],1,N,root[x]);
    return temp;
}

map mp;
int main(){
    init();
    scanf("%d%d",&N,&Q);
    for(int i=1;i<=N;i++)
      scanf("%d",&A[i]);
    int x,y;
    for(int i=0;i



你可能感兴趣的:(————ACM相关————,——数据结构——,ACM,-,主席树)