zoukankan      html  css  js  c++  java
  • [BZOJ 4999]This Problem Is Too Simple!

    [BZOJ 4999]This Problem Is Too Simple!

    题目

    给您一颗树,每个节点有个初始值。
    现在支持以下两种操作:
    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

    OUTPUT

    0

    1

    1

    0

    解题报告

    树剖+权值线段树动态开点+离散

    随便搞搞就行了

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<map>
      5 using namespace std;
      6 inline int read(){
      7     int sum(0);
      8     char ch(getchar());
      9     for(;ch<'0'||ch>'9';ch=getchar());
     10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
     11     return sum;
     12 }
     13 struct edge{
     14     int e;
     15     edge *n;
     16 }ed[200005],*pre[100005];
     17 int tot;
     18 inline void insert(int s,int e){
     19     ed[++tot].e=e;
     20     ed[tot].n=pre[s];
     21     pre[s]=&ed[tot];
     22 }
     23 map<int,int>ma;
     24 int num;
     25 int n,q;
     26 int a[100005];
     27 int dep[100005],size[100005],fa[100005],son[100005];
     28 inline void dfs1(int u){
     29     size[u]=1;
     30     son[u]=0;
     31     for(edge *i=pre[u];i;i=i->n){
     32         int e(i->e);
     33         if(e!=fa[u]){
     34             fa[e]=u;
     35             dep[e]=dep[u]+1;
     36             dfs1(e);
     37             size[u]+=size[e];
     38             if(size[e]>size[son[u]])
     39                 son[u]=e;
     40         }
     41     }
     42 }
     43 int timee;
     44 int id[100005],pos[100005],top[100005];
     45 inline void dfs2(int u,int rt){
     46     top[u]=rt;
     47     id[u]=++timee;
     48     pos[timee]=u;
     49     if(son[u])
     50         dfs2(son[u],rt);
     51     for(edge *i=pre[u];i;i=i->n){
     52         int e(i->e);
     53         if(e!=fa[u]&&e!=son[u])
     54             dfs2(e,e);
     55     }
     56 }
     57 int cnt;
     58 int rt[300005],lch[12000005],rch[12000005],sum[12000005];
     59 inline void update(int &x,int pos,int w,int l,int r){
     60     if(!x)
     61         x=++cnt;
     62     sum[x]+=w;
     63     if(l==r)
     64         return;
     65     int mid((l+r)>>1);
     66     if(pos<=mid)
     67         update(lch[x],pos,w,l,mid);
     68     else
     69         update(rch[x],pos,w,mid+1,r);
     70 }
     71 inline int query(int x,int ll,int rr,int l,int r){
     72     if(!x)
     73         return 0;
     74     if(ll<=l&&r<=rr)
     75         return sum[x];
     76     int mid((l+r)>>1),ret(0);
     77     if(ll<=mid)
     78         ret+=query(lch[x],ll,rr,l,mid);
     79     if(mid<rr)
     80         ret+=query(rch[x],ll,rr,mid+1,r);
     81     return ret;
     82 }
     83 inline int ask(int x,int y,int z){
     84     int ret(0),tmp(ma[z]);
     85     while(top[x]^top[y]){
     86         if(dep[top[x]]<dep[top[y]])
     87             swap(x,y);
     88         ret+=query(rt[tmp],id[top[x]],id[x],1,n);
     89         x=fa[top[x]];
     90     }
     91     if(dep[x]>dep[y])
     92         swap(x,y);
     93     ret+=query(rt[tmp],id[x],id[y],1,n);
     94     return ret;
     95 }
     96 char op[2];
     97 int main(){
     98     memset(pre,NULL,sizeof(pre));
     99     n=read(),q=read();
    100     for(int i=1;i<=n;++i)
    101         a[i]=read();
    102     for(int i=1;i<n;++i){
    103         int x(read()),y(read());
    104         insert(x,y),insert(y,x);
    105     }
    106     dfs1(1);
    107     dfs2(1,1);
    108     for(int i=1;i<=n;++i){
    109         if(!ma[a[i]])
    110             ma[a[i]]=++num;
    111         update(rt[ma[a[i]]],id[i],1,1,n);
    112     }
    113     while(q--){
    114         scanf("%s",op);
    115         if(op[0]=='C'){
    116             int x(read()),y(read());
    117             update(rt[ma[a[x]]],id[x],-1,1,n);
    118             if(!ma[y])
    119                 ma[y]=++num;
    120             a[x]=y;
    121             update(rt[ma[y]],id[x],1,1,n);
    122         }
    123         else{
    124             int x(read()),y(read()),z(read());
    125             if(!ma[z])
    126                 puts("0");
    127             else
    128                 printf("%d
    ",ask(x,y,z));
    129         }
    130     }
    131 }
    View Code
  • 相关阅读:
    用户自定义控件的嵌套问题
    ASP.NET进阶:调用Javascript
    [网络收集]FCKeditor配置和精简【附源码】
    检查session判断用户是否退出登录
    Server.Transfer VS Response.Redirect
    asp.net下ckeditor3.0.1和ckfinder_aspnet_1.4.1.1的配置方法
    Sudoku(数独)
    转自:蓝色污点的专栏
    LETTERS(字母)
    放苹果
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7598946.html
Copyright © 2011-2022 走看看