• HZOJ 模板(ac)


    调了一天,恶心死我了……作者的题解水的一b……

    测试点1~6:

    暴力修改查询即可,期望得分30。

    测试点7~14:

    k=1e5,相当于没有限制,那么对于树上每个点建权值线段树,线段树合并即可。

    期望的分40,结合算法1 70分。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #define MAXN 100010
      6 #define LL long long
      7 #define int LL
      8 #define ma(x,y) memset(x,y,sizeof(x))
      9 using namespace std;
     10 struct edge
     11 {
     12     int u,v,nxt;
     13     #define u(x) ed[x].u
     14     #define v(x) ed[x].v
     15     #define n(x) ed[x].nxt
     16 }ed[MAXN*2];
     17 int first[MAXN],num_e;
     18 #define f(x) first[x]
     19 int n,m,k[MAXN],Q,tc[MAXN];
     20 struct tree
     21 {
     22     int ls,rs,sum;    
     23     #define ls(x) tr[x].ls
     24     #define rs(x) tr[x].rs
     25     #define sum(x) tr[x].sum
     26 }tr[MAXN*200];
     27 int cnt,T[MAXN];
     28 int sum[1010][1010],fa[MAXN],maxc;
     29 void add(int &x,int l,int r,int L,int R)
     30 {
     31     if(!x)x=++cnt;    
     32     if(l==r){sum(x)|=1;return;}
     33     int mid=(l+r)>>1;
     34     if(L<=mid)add(ls(x),l,mid,L,R);
     35     if(R>mid) add(rs(x),mid+1,r,L,R);
     36     sum(x)=sum(ls(x))+sum(rs(x));
     37 }
     38 int ask(int x,int l,int r,int L,int R)
     39 {
     40     if(l>=L&&r<=R)return sum(x);
     41     int mid=(l+r)>>1,ans=0;
     42     if(L<=mid)ans+=ask(ls(x),l,mid,L,R);
     43     if(R>mid) ans+=ask(rs(x),mid+1,r,L,R);
     44     return ans;
     45 }
     46 int merge(int x,int y)
     47 {    
     48     if(!x||!y)return x+y;
     49     ls(x)=merge(ls(x),ls(y));
     50     rs(x)=merge(rs(x),rs(y));
     51     if(!ls(x)&&!rs(x))sum(x)=sum(x)|sum(y);
     52     else sum(x)=sum(ls(x))+sum(rs(x));
     53     return x;
     54 }
     55 int ans[MAXN],x[MAXN],c[MAXN];
     56 void dfs(int x,int fa)
     57 {
     58     for(int i=f(x);i;i=n(i))
     59     if(v(i)!=fa)
     60     {    
     61         dfs(v(i),x);
     62         ans[v(i)]=ask(T[v(i)],1,maxc,1,maxc);
     63         T[x]=merge(T[x],T[v(i)]);
     64     }
     65 }
     66 void dfs2(int x,int ff)
     67 {
     68     fa[x]=ff;
     69     for(int i=f(x);i;i=n(i))
     70     if(v(i)!=ff)
     71         dfs2(v(i),x);
     72 }
     73 inline int read();
     74 inline void adde(int u,int v);
     75 signed main()
     76 {
     77     n=read();int tu,tv;
     78     for(int i=1;i<n;i++)
     79     {    
     80         tu=read(),tv=read();    
     81         adde(tu,tv),adde(tv,tu);
     82     }
     83     for(int i=1;i<=n;i++)k[i]=read();    
     84     m=read();
     85     dfs2(1,0);
     86     if(n<=1000&&m<=1000)//暴力
     87     {
     88         LL tem,ac;LL x,c;
     89         for(int i=1;i<=m;i++)
     90         {
     91             x=read();c=read();
     92             maxc=max(maxc,c);
     93             tem=x;
     94             while(tem)
     95             {
     96                 if(sum[tem][0]<k[tem])
     97                 sum[tem][0]++,sum[tem][c]++;
     98                 tem=fa[tem];
     99             }
    100         }
    101         Q=read();
    102         for(int i=1;i<=Q;i++)    
    103         {
    104             tem=read();ac=0;
    105             for(int j=1;j<=maxc;j++)
    106             if(sum[tem][j]!=0)ac++;
    107             printf("%lld
    ",ac);
    108         }
    109         return 0;
    110     }
    111     for(int i=1;i<=m;i++)
    112     {
    113         x[i]=read(),c[i]=read(),tc[i]=c[i];
    114         maxc=max(maxc,c[i]);
    115     }
    116     sort(tc+1,tc+1+m);maxc=m;
    117     int ooo=unique(tc+1,tc+1+m)-tc-1;
    118     for(int i=1;i<=m;i++)
    119         c[i]=lower_bound(tc+1,tc+ooo+1,c[i])-tc;
    120     for(int i=1;i<=m;i++)
    121         add(T[x[i]],1,maxc,c[i],c[i]);
    122     dfs(1,0);
    123     Q=read();
    124     ans[1]=ask(T[1],1,maxc,1,maxc);
    125     for(int i=1;i<=Q;i++)
    126     {
    127         x[i]=read();printf("%lld
    ",ans[x[i]]);
    128     }
    129 }
    130 inline int read()
    131 {
    132     int s=0,f=1;char a=getchar();
    133     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();    }
    134     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    135     return s*f;
    136 }
    137 inline void adde(int u,int v)
    138 {
    139     ++num_e;
    140     u(num_e)=u;
    141     v(num_e)=v;
    142     n(num_e)=f(u);
    143     f(u)=num_e;
    144 }
    View Code

    测试点15~20:

    最恶心的几个点,用到了树上启发式合并+树链剖分思想。

    考虑以时间为线段树下标建立权值线段树,维护这段时间内小球的颜色种类数以及小球总数,用一个桶记录每个颜色出现的最早时间。对于每个节点建立一个vector,将关于这个节点的操作color,time二元组扔到这个节点的vector中。

    首先一边dfs求出每个点的重儿子,要用重儿子来保证复杂度,证明见这里

    这里先说一下不保证复杂度但是好理解而且可以救回来的思路:

    然后第二遍dfs统计答案:先处理儿子(注意每次要清空桶,但是不要memset),然后将这个节点的所有操作扔到他的重儿子的vector中,互换(相当于将重儿子的操作扔到这个节点),然后枚举儿子,将其他儿子的操作合并,接下来就是统计这个点的答案了:首先确保此时桶是空的,然后枚举这个节点vector中的操作,如果当前小球未出现过直接更新线段树,如果在一个更晚的时间出现则在那个时间种类数减1,这个时间种类数+1。最后个数加1.然后说一下线段树的查询操作,和主席树的思想类似(直接上代码):

     1 int ask(int x,int l,int r,int num)
     2 {
     3     if(num<=0)return 0;
     4     if(l==r)return sum(x);        
     5     int ans=0,mid=(l+r)>>1;
     6     if(num(ls(x))<=num)    
     7     {
     8         ans+=sum(ls(x));
     9         ans+=ask(rs(x),mid+1,r,num-num(ls(x)));
    10         return ans;
    11     }
    12     else return ask(ls(x),l,mid,num);
    13 }
      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #define MAXN 100010
      7 #define LL long long
      8 #define MP(a,b) make_pair(a,b)
      9 #define ma(x) memest(x,0,sizeof(x))
     10 using namespace std;
     11 struct edge
     12 {
     13     int u,v,nxt;
     14     #define u(x) ed[x].u
     15     #define v(x) ed[x].v
     16     #define n(x) ed[x].nxt
     17 }ed[MAXN*2];
     18 int first[MAXN],num_e;
     19 #define f(x) first[x]
     20 int n,m,k[MAXN],Q,tc[MAXN];
     21 vector<pair<int,int> >cz[MAXN];
     22 struct tree
     23 {
     24     int ls,rs,sum,num;    
     25     #define ls(x) tr[x].ls
     26     #define rs(x) tr[x].rs
     27     #define sum(x) tr[x].sum    
     28     #define num(x) tr[x].num
     29 }tr[MAXN*1000];
     30 int cnt,T[MAXN],maxc;
     31 int ans[MAXN],x[MAXN],c[MAXN];
     32 int t[MAXN];
     33 int son[MAXN],size[MAXN];
     34 void add(int &x,int l,int r,int t,int tx,int y)
     35 {
     36     if(!x)x=++cnt;
     37     if(l==r){sum(x)+=tx;num(x)+=y;return;}
     38     int mid=(l+r)>>1;
     39     if(t<=mid)add(ls(x),l,mid,t,tx,y);
     40     else add(rs(x),mid+1,r,t,tx,y);
     41     sum(x)=sum(ls(x))+sum(rs(x));
     42     num(x)=num(ls(x))+num(rs(x));
     43 }
     44 int ask(int x,int l,int r,int num)
     45 {
     46     if(num<=0)return 0;
     47     if(l==r)return sum(x);        
     48     int ans=0,mid=(l+r)>>1;
     49     if(num(ls(x))<=num)    
     50     {
     51         ans+=sum(ls(x));
     52         ans+=ask(rs(x),mid+1,r,num-num(ls(x)));
     53         return ans;
     54     }
     55     else return ask(ls(x),l,mid,num);
     56 }
     57 void merge(int x,int y)
     58 {    
     59     for(int i=0;i<cz[y].size();i++)
     60         cz[x].push_back(cz[y][i]);
     61     cz[y].clear();
     62 }
     63 void clear(int x)
     64 {    
     65     for(int i=0;i<cz[x].size();i++)
     66         t[cz[x][i].first]=0;
     67 }
     68 void dfs2(int x,int fa)
     69 {    
     70     for(int i=f(x);i;i=n(i))
     71     if(v(i)!=fa)
     72     {
     73         dfs2(v(i),x);
     74         clear(v(i));
     75     }
     76     if(son[x])
     77     {
     78         merge(son[x],x);
     79         swap(cz[son[x]],cz[x]);
     80     }
     81     for(int i=f(x);i;i=n(i))
     82     if(v(i)!=fa)merge(x,v(i));
     83     for(int i=0;i<cz[x].size();i++)
     84     {
     85         int t1=cz[x][i].first,t2=cz[x][i].second;
     86         if(!t[t1])    
     87             add(T[x],1,m,t2,1,0),t[t1]=t2;
     88         else if(t[t1]>t2)
     89         {
     90             add(T[x],1,m,t[t1],-1,0);
     91             add(T[x],1,m,t2,1,0);
     92             t[t1]=t2;
     93         }
     94         add(T[x],1,m,t2,0,1);
     95     }
     96     ans[x]=ask(T[x],1,m,k[x]);
     97 }
     98 inline int read();
     99 void dfs(int x,int fa);
    100 inline void adde(int u,int v);
    101 signed main()
    102 {
    103 //    freopen("in.txt","r",stdin);
    104 
    105     n=read();int tu,tv;
    106     for(int i=1;i<n;i++)
    107     {    
    108         tu=read(),tv=read();    
    109         adde(tu,tv),adde(tv,tu);
    110     }
    111     for(int i=1;i<=n;i++)k[i]=read();    
    112     m=read();
    113     for(int i=1;i<=m;i++)
    114     {
    115         x[i]=read(),c[i]=read(),tc[i]=c[i];
    116         maxc=max(maxc,c[i]);
    117     }
    118     sort(tc+1,tc+1+m);maxc=m;
    119     int ooo=unique(tc+1,tc+1+m)-tc-1;
    120     for(int i=1;i<=m;i++)
    121         c[i]=lower_bound(tc+1,tc+ooo+1,c[i])-tc;
    122     for(int i=1;i<=m;i++)
    123         cz[x[i]].push_back(MP(c[i],i));
    124     dfs(1,0);
    125     dfs2(1,0);
    126     Q=read();
    127     for(int i=1;i<=Q;i++)
    128         x[i]=read(),printf("%d
    ",ans[x[i]]);
    129 }
    130 inline int read()
    131 {
    132     int s=0,f=1;char a=getchar();
    133     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();    }
    134     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    135     return s*f;
    136 }
    137 inline void adde(int u,int v)
    138 {
    139     ++num_e;
    140     u(num_e)=u;
    141     v(num_e)=v;
    142     n(num_e)=f(u);
    143     f(u)=num_e;
    144 }
    145 void dfs(int x,int fa)
    146 {
    147     size[x]=1;
    148     for(int i=f(x);i;i=n(i))
    149     if(v(i)!=fa)
    150     {
    151         dfs(v(i),x);
    152         size[x]+=size[v(i)];
    153         if(size[v(i)]>size[son[x]])son[x]=v(i);
    154     }
    155 }
    接近正解的T30代码

    到这里就结束了,然后你应该就会发现你T30了,因为以上算法是不保证时间复杂度的,原因在于处理重儿子后清空桶花费了过长时间。但是如果不清空桶下面的答案查询就会出错,那怎么办呢?

    其实可以在处理完所有轻儿子后在处理重儿子,此后不清空桶,而是直接T[x]=T[son[x]](根节点),直接从重儿子的线段树上开始修改,这样时间复杂度就有保证了。还有一点是这样要在最后才把重儿子的操作合并。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #define MAXN 100010
      7 #define LL long long
      8 #define int LL
      9 #define MP(a,b) make_pair(a,b)
     10 #define ma(x) memest(x,0,sizeof(x))
     11 using namespace std;
     12 struct edge
     13 {
     14     int u,v,nxt;
     15     #define u(x) ed[x].u
     16     #define v(x) ed[x].v
     17     #define n(x) ed[x].nxt
     18 }ed[MAXN*2];
     19 int first[MAXN],num_e;
     20 #define f(x) first[x]
     21 int n,m,k[MAXN],Q,tc[MAXN];
     22 vector<pair<int,int> >cz[MAXN];
     23 struct tree
     24 {
     25     int ls,rs,sum,num;    
     26     #define ls(x) tr[x].ls
     27     #define rs(x) tr[x].rs
     28     #define sum(x) tr[x].sum    
     29     #define num(x) tr[x].num
     30 }tr[MAXN*200];
     31 int cnt,T[MAXN],maxc;
     32 int ans[MAXN],x[MAXN],c[MAXN];
     33 int t[MAXN];
     34 int son[MAXN],size[MAXN];
     35 void add(int &x,int l,int r,int t,int tx,int y)
     36 {
     37     if(!x)x=++cnt;
     38     if(l==r){sum(x)+=tx;num(x)+=y;return;}
     39     int mid=(l+r)>>1;
     40     if(t<=mid)add(ls(x),l,mid,t,tx,y);
     41     else add(rs(x),mid+1,r,t,tx,y);
     42     sum(x)=sum(ls(x))+sum(rs(x));
     43     num(x)=num(ls(x))+num(rs(x));
     44 }
     45 int ask(int x,int l,int r,int num)
     46 {
     47     if(num<=0)return 0;
     48     if(l==r)return sum(x);        
     49     int ans=0,mid=(l+r)>>1;
     50     if(num(ls(x))<=num)    
     51     {
     52         ans+=sum(ls(x));
     53         ans+=ask(rs(x),mid+1,r,num-num(ls(x)));
     54         return ans;
     55     }
     56     else return ask(ls(x),l,mid,num);
     57 }
     58 void merge(int x,int y)
     59 {    
     60     for(int i=0;i<cz[y].size();i++)
     61         cz[x].push_back(cz[y][i]);
     62     cz[y].clear();
     63 }
     64 void clear(int x)
     65 {    
     66     for(int i=0;i<cz[x].size();i++)
     67         t[cz[x][i].first]=0;
     68 }
     69 void dfs2(int x,int fa)
     70 {    
     71     for(int i=f(x);i;i=n(i))
     72     if(v(i)!=fa&&v(i)!=son[x])
     73     {
     74         dfs2(v(i),x);
     75         clear(v(i));
     76     }
     77     if(son[x])dfs2(son[x],x);
     78     if(son[x])T[x]=T[son[x]];    
     79     for(int i=f(x);i;i=n(i))
     80     if(v(i)!=fa&&v(i)!=son[x])merge(x,v(i));
     81     for(int i=0;i<cz[x].size();i++)
     82     {
     83         int t1=cz[x][i].first,t2=cz[x][i].second;
     84         if(!t[t1])add(T[x],1,m,t2,1,0),t[t1]=t2;
     85         else if(t[t1]>t2)
     86         {
     87             add(T[x],1,m,t[t1],-1,0);
     88             add(T[x],1,m,t2,1,0);
     89             t[t1]=t2;
     90         }
     91         add(T[x],1,m,t2,0,1);
     92     }
     93     ans[x]=ask(T[x],1,m,k[x]);
     94     if(son[x])
     95     {
     96         merge(son[x],x);
     97         swap(cz[son[x]],cz[x]);
     98     }
     99 }
    100 inline int read();
    101 void dfs(int x,int fa);
    102 inline void adde(int u,int v);
    103 signed main()
    104 {
    105 //    freopen("in.txt","r",stdin);
    106 
    107     n=read();int tu,tv;
    108     for(int i=1;i<n;i++)
    109     {    
    110         tu=read(),tv=read();    
    111         adde(tu,tv),adde(tv,tu);
    112     }
    113     for(int i=1;i<=n;i++)k[i]=read();    
    114     m=read();
    115     for(int i=1;i<=m;i++)
    116     {
    117         x[i]=read(),c[i]=read(),tc[i]=c[i];
    118         maxc=max(maxc,c[i]);
    119     }
    120     sort(tc+1,tc+1+m);maxc=m;
    121     int ooo=unique(tc+1,tc+1+m)-tc-1;
    122     for(int i=1;i<=m;i++)
    123         c[i]=lower_bound(tc+1,tc+ooo+1,c[i])-tc;
    124     for(int i=1;i<=m;i++)
    125         cz[x[i]].push_back(MP(c[i],i));
    126     dfs(1,0);dfs2(1,0);
    127     Q=read();
    128     for(int i=1;i<=Q;i++)
    129         x[i]=read(),printf("%lld
    ",ans[x[i]]);
    130 }
    131 inline int read()
    132 {
    133     int s=0,f=1;char a=getchar();
    134     while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();    }
    135     while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
    136     return s*f;
    137 }
    138 inline void adde(int u,int v)
    139 {
    140     ++num_e;
    141     u(num_e)=u;
    142     v(num_e)=v;
    143     n(num_e)=f(u);
    144     f(u)=num_e;
    145 }
    146 void dfs(int x,int fa)
    147 {
    148     size[x]=cz[x].size();
    149     for(int i=f(x);i;i=n(i))
    150     if(v(i)!=fa)
    151     {
    152         dfs(v(i),x);
    153         size[x]+=size[v(i)];
    154         if(size[v(i)]>size[son[x]])son[x]=v(i);
    155     }
    156 }
    完整代码
  • 相关阅读:
    Vue基础简介
    Vue基础简介
    django生命周期请求l流程图
    CSRF与auth模块
    cookie与session django中间件
    Django forms组件与钩子函数
    ajax结合sweetalert实现删除按钮动态效果
    ajax数据交互
    如何绕过CDN找源站ip
    IP地址的另一种形式---一种隐藏IP的方法
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11264199.html
Copyright © 2020-2023  润新知