【集训第一天·特来卖萌】树链剖分之水水的例题

     今天学习了树链剖分并且做了几道很有意思的题。。。

      树链剖分的大致思想就是把一棵树转化成一条链(一个序列),然

后在上面做一些处理,例如:线段树。树转链的方法大致类似于 dfs

序,但是多了一个重边的处理。

      上水题。(题名自行google)

      1.BZOJ1036 ZJOJ2008 树的统计Count

      标准模板题,超级水0.0。。。。。。

CODE:

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<stack>
  4 #include<queue>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<cmath>
  9 #define inf 0x3f3f3f3f
 10 #define ll long long
 11 #define maxn  30005
 12 #define lson u<<1,l,mid
 13 #define rson u<<1|1,mid+1,r
 14 using namespace std;
 15 int w[maxn],head[maxn],tid[maxn],size[maxn],id[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],ecnt=1,cnt;
 16 
 17 struct edge{
 18     int v,next;
 19 }e[maxn*2];
 20 
 21 void adde(int u,int v){
 22     e[ecnt].v=v;
 23     e[ecnt].next=head[u];
 24     head[u]=ecnt++;
 25 }
 26 
 27 void dfs1(int u,int pre){
 28     dep[u]=dep[pre]+1;
 29     fa[u]=pre;
 30     size[u]=1;
 31     int msum=0;
 32     for(int i=head[u];i;i=e[i].next){
 33         int v=e[i].v;
 34         if(v==pre)continue;
 35         dfs1(v,u);
 36         size[u]+=size[v];
 37         if(size[v]>msum){
 38             msum=size[v];
 39             son[u]=v;
 40         }
 41     }
 42 }
 43 
 44 void dfs2(int u,int anc){
 45     tid[u]=++cnt;
 46     top[u]=anc;
 47     id[cnt]=u;
 48     if(son[u])dfs2(son[u],anc);
 49     for(int i=head[u];i;i=e[i].next){
 50         int v=e[i].v;
 51         if(v==son[u]||v==fa[u])continue;
 52         dfs2(v,v);
 53     }
 54 }
 55 
 56 struct node{
 57     int l,r,ma,sum;
 58 }t[4*maxn];
 59 
 60 void update(int u){
 61     t[u].sum=t[u<<1].sum+t[u<<1|1].sum;
 62     t[u].ma=max(t[u<<1].ma,t[u<<1|1].ma);
 63 }
 64 
 65 void build(int u,int l,int r){
 66     t[u].l=l;
 67     t[u].r=r;
 68     if(l==r){
 69         t[u].sum=t[u].ma=w[id[l]];
 70         return;
 71     }
 72     int mid=(l+r)>>1;
 73     build(lson);
 74     build(rson);
 75     update(u);
 76 }
 77 
 78 int askmax(int u,int l,int r){
 79     if(t[u].r==r&&t[u].l==l)return t[u].ma;
 80     int mid=(t[u].l+t[u].r)>>1;
 81     if(r<=mid)return askmax(u<<1,l,r);
 82     if(l>mid)return askmax(u<<1|1,l,r);
 83     else return max(askmax(u<<1,l,mid),askmax(u<<1|1,mid+1,r));
 84 }
 85 
 86 int asksum(int u,int l,int r){
 87     if(t[u].r==r&&t[u].l==l)return t[u].sum;
 88     int mid=(t[u].l+t[u].r)>>1;
 89     if(r<=mid)return asksum(u<<1,l,r);
 90     if(l>mid)return asksum(u<<1|1,l,r);
 91     else return asksum(u<<1,l,mid)+asksum(u<<1|1,mid+1,r);
 92 }
 93 
 94 int findsum(int u,int v){
 95     int fu=top[u],fv=top[v];
 96     int tmp=0;
 97     while(fu!=fv){
 98         if(dep[fu]<dep[fv]){
 99             swap(fu,fv);
100             swap(u,v);
101         }
102         tmp+=asksum(1,tid[fu],tid[u]);
103         u=fa[fu];
104         fu=top[u];
105     }
106     if(dep[u]>dep[v])swap(u,v);
107     return tmp+asksum(1,tid[u],tid[v]);
108 }
109 
110 int findmax(int u,int v){
111     int fu=top[u],fv=top[v];
112     int tmp=-99999999;
113     while(fu!=fv){
114         if(dep[fu]<dep[fv]){
115             swap(fu,fv);
116             swap(u,v);
117         }
118         tmp=max(tmp,askmax(1,tid[fu],tid[u]));
119         u=fa[fu];
120         fu=top[u];
121     }
122     if(dep[u]>dep[v])swap(u,v);
123     return max(tmp,askmax(1,tid[u],tid[v]));
124 }
125 
126 void change(int u,int k,int val){
127     if(t[u].l==k&&t[u].r==k){
128         t[u].ma=t[u].sum=val;
129         return;
130     }
131     int mid=(t[u].l+t[u].r)>>1;
132     if(k<=mid)change(u<<1,k,val);
133     else change(u<<1|1,k,val);
134     update(u);
135 }
136 
137 int main(){
138     int n,m;
139     scanf("%d",&n);
140     int a,b;
141     for(int i=1;i<n;i++)scanf("%d%d",&a,&b),adde(a,b),adde(b,a);
142     for(int i=1;i<=n;i++)scanf("%d",&w[i]),t[i].ma=-99999999;
143     dfs1(1,0);
144     dfs2(1,1);
145     build(1,1,n);
146     scanf("%d",&m);
147     for(int i=1;i<=m;i++){
148         char s[100];
149         scanf("%s",s);
150         scanf("%d%d",&a,&b);
151         if(s[0]=='C')change(1,tid[a],b);
152         else if(!strcmp(s,"QMAX"))printf("%d\n",findmax(a,b));
153         else printf("%d\n",findsum(a,b));
154     }
155     return 0;
156 }
想不想看???

 

    2. BZOJ3626 LNOI2014 LCA

      这东西非常扯淡,题解和题名完全不是一个等级的东西(⊙o⊙)

  这里简单地说说思路   更多细节参考 http://www.cnblogs.com/Paul-Guderian/p/6628570.html

  ①利用铺路的思想,把题目所给的每个区间中的点都一步步走回根节点,路上经过的节点点权+1。再考虑 Z(题目要求查询的节点),从Z节点向根走,把路上经过的所有节点的权值加起来,即为所求。

  ②我们求的时 [l,r]区间内的点和Z的lca的深度和,即[l,r](z)  

  那么可用前缀思想把它转化为[1,r](z)-[1,l-1](z)

  把输入的区间存入一个结构体数组(l存一个,r再存一个,l的结构体存符号"-",r存"+"),排序。

  当走到端点值时进行操作,给所对应的询问标号加上或减去具体的答案。

      PS:通过此方法可以省时间并且符合节点遍历顺序,具体操作见代码

CODE:

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define ll long long
  7 #define inf 1000000000
  8 #define mod 201314
  9 using namespace std;
 10 inline ll read()
 11 {
 12     ll x=0,f=1;char ch=getchar();
 13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 int n,m,cnt,place;
 18 int bin[20];
 19 int son[50005],last[50005],fa[50005],belong[50005],pl[50005],deep[50005];
 20 struct edge{int to,next;}e[50005];
 21 struct que{int z,ans1,ans2;}q[50005];
 22 struct data{int num,p;bool flag;}a[100005];
 23 struct seg{int l,r,sum,tag,size;}t[200005];
 24 inline bool operator<(data a,data b)
 25 {
 26     return a.p<b.p;
 27 }
 28 inline void insert(int u,int v)
 29 {
 30     e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
 31 }
 32 void dfs1(int x)
 33 {
 34     son[x]=1;
 35     for(int i=last[x];i;i=e[i].next)
 36     {
 37         if(e[i].to==fa[x])continue;
 38         deep[e[i].to]=deep[x]+1;
 39         fa[e[i].to]=x;
 40         dfs1(e[i].to);
 41         son[x]+=son[e[i].to];
 42     }
 43 }
 44 void dfs2(int x,int chain)
 45 {
 46     belong[x]=chain;pl[x]=++place;
 47     int k=n;
 48     for(int i=last[x];i;i=e[i].next)
 49         if(e[i].to!=fa[x]&&son[e[i].to]>son[k])
 50             k=e[i].to;
 51     if(k!=n)dfs2(k,chain);
 52     for(int i=last[x];i;i=e[i].next)
 53         if(e[i].to!=fa[x]&&e[i].to!=k)
 54             dfs2(e[i].to,e[i].to);
 55 }
 56 inline void pushdown(int k)
 57 {
 58     if(t[k].l==t[k].r||!t[k].tag)return;
 59     int tag=t[k].tag;t[k].tag=0;
 60     t[k<<1].sum=t[k<<1].sum+t[k<<1].size*tag;
 61     t[k<<1|1].sum=t[k<<1|1].sum+t[k<<1|1].size*tag;
 62     t[k<<1].tag=t[k<<1].tag+tag;
 63     t[k<<1|1].tag=t[k<<1|1].tag+tag;
 64 }
 65 void build(int k,int l,int r)
 66 {
 67     t[k].l=l;t[k].r=r;t[k].size=r-l+1;
 68     if(l==r)return;
 69     int mid=(l+r)>>1;
 70     build(k<<1,l,mid);
 71     build(k<<1|1,mid+1,r);
 72 }
 73 void update(int k,int x,int y)
 74 {
 75     pushdown(k);
 76     int l=t[k].l,r=t[k].r;
 77     if(l==x&&y==r)
 78     {
 79         t[k].tag++;t[k].sum+=t[k].size;
 80         return;
 81     }
 82     int mid=(l+r)>>1;
 83     if(y<=mid)update(k<<1,x,y);
 84     else if(x>mid)update(k<<1|1,x,y);
 85     else 
 86     {
 87         update(k<<1,x,mid);
 88         update(k<<1|1,mid+1,y);
 89     }
 90     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
 91 }
 92 void solve_update(int x,int f)
 93 {
 94     while(belong[x]!=belong[f])
 95     {
 96         update(1,pl[belong[x]],pl[x]);
 97         x=fa[belong[x]];
 98     }
 99     update(1,pl[f],pl[x]);
100 }
101 int query(int k,int x,int y)
102 {
103     pushdown(k);
104     int l=t[k].l,r=t[k].r;
105     if(l==x&&y==r)return t[k].sum;
106     int mid=(l+r)>>1;
107     if(y<=mid)return query(k<<1,x,y);
108     else if(x>mid)return query(k<<1|1,x,y);
109     else return query(k<<1,x,mid)+query(k<<1|1,mid+1,y);
110 }
111 int solve_query(int x,int f)
112 {
113     int sum=0;
114     while(belong[x]!=belong[f])
115     {
116         sum+=query(1,pl[belong[x]],pl[x]);
117         sum%=mod;
118         x=fa[belong[x]];
119     }
120     sum+=query(1,pl[f],pl[x]);sum%=mod;
121     return sum;
122 }
123 int main()
124 {
125     //freopen("lca.in","r",stdin);
126     //freopen("lca.out","w",stdout);
127     bin[0]=1;for(int i=1;i<20;i++)bin[i]=(bin[i-1]<<1);
128     n=read();m=read();
129     for(int i=1;i<n;i++)
130     {
131         int x=read();insert(x,i);
132     }
133     int tot=0;
134     for(int i=1;i<=m;i++)
135     {
136         int l=read(),r=read();
137         q[i].z=read();
138         a[++tot].p=l-1;a[tot].num=i;a[tot].flag=0;
139         a[++tot].p=r;a[tot].num=i;a[tot].flag=1;
140     }
141     build(1,1,n);
142     sort(a+1,a+tot+1);
143     dfs1(0);dfs2(0,0);
144     int now=-1;
145     for(int i=1;i<=tot;i++)
146     {
147         while(now<a[i].p)
148         {
149             now++;
150             solve_update(now,0);
151         }
152         int t=a[i].num;
153         if(!a[i].flag)q[t].ans1=solve_query(q[t].z,0);
154         else q[t].ans2=solve_query(q[t].z,0);
155     }
156     for(int i=1;i<=m;i++)
157         printf("%d\n",(q[i].ans2-q[i].ans1+mod)%mod);
158     return 0;
159 }
看吗??

     

  3.NOIP2015运输计划

  这个题很有意思 二分答案+树链剖分+差分数组

  大致思路:

 

  首先预处理出每个货物送达的初始距离,用lca(tarjan,倍增,暴力,树链剖分--方法自便)+dis数组求出。sort一遍,把距离大的放在数组后面。二分最大时间最小值,找出大于这个时间的货物然后让这些货物铺路,找出这些货物共同经过的某些路(称为共路),遍历共路,找出最长共路。若 二分的答案+此共路的长度>=最大货物运输距离,则check通过。

      另外,这个题也使用了上题铺路的思想,只不过使用差分实现的。

  的用树链剖分把这棵树映射到一条链上利用差分,每个货物进一条链时,在链的首部给通货量+1,出去时在出去的节点-1。

     PS:注意此题给的是边权,可通过下放给儿子节点的方式来转化为点权,且差分时注意  脚标+1,详见代码。

CODE:

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define ll long long
  7 #define inf 1000000000
  8 #define mod 201314
  9 using namespace std;
 10 inline ll read()
 11 {
 12     ll x=0,f=1;char ch=getchar();
 13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 int n,m,cnt,place;
 18 int bin[20];
 19 int son[50005],last[50005],fa[50005],belong[50005],pl[50005],deep[50005];
 20 struct edge{int to,next;}e[50005];
 21 struct que{int z,ans1,ans2;}q[50005];
 22 struct data{int num,p;bool flag;}a[100005];
 23 struct seg{int l,r,sum,tag,size;}t[200005];
 24 inline bool operator<(data a,data b){
 25     return a.p<b.p;
 26 }
 27 inline void insert(int u,int v){
 28     e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
 29 }
 30 void dfs1(int x){
 31     son[x]=1;
 32     for(int i=last[x];i;i=e[i].next){
 33         if(e[i].to==fa[x])continue;
 34         deep[e[i].to]=deep[x]+1;
 35         fa[e[i].to]=x;
 36         dfs1(e[i].to);
 37         son[x]+=son[e[i].to];
 38     }
 39 }
 40 void dfs2(int x,int chain){
 41     belong[x]=chain;pl[x]=++place;
 42     int k=n;
 43     for(int i=last[x];i;i=e[i].next)
 44         if(e[i].to!=fa[x]&&son[e[i].to]>son[k])
 45             k=e[i].to;
 46     if(k!=n)dfs2(k,chain);
 47     for(int i=last[x];i;i=e[i].next)
 48         if(e[i].to!=fa[x]&&e[i].to!=k)
 49             dfs2(e[i].to,e[i].to);
 50 }
 51 inline void pushdown(int k){
 52     if(t[k].l==t[k].r||!t[k].tag)return;
 53     int tag=t[k].tag;t[k].tag=0;
 54     t[k<<1].sum=t[k<<1].sum+t[k<<1].size*tag;
 55     t[k<<1|1].sum=t[k<<1|1].sum+t[k<<1|1].size*tag;
 56     t[k<<1].tag=t[k<<1].tag+tag;
 57     t[k<<1|1].tag=t[k<<1|1].tag+tag;
 58 }
 59 void build(int k,int l,int r){
 60     t[k].l=l;t[k].r=r;t[k].size=r-l+1;
 61     if(l==r)return;
 62     int mid=(l+r)>>1;
 63     build(k<<1,l,mid);
 64     build(k<<1|1,mid+1,r);
 65 }
 66 void update(int k,int x,int y){
 67     pushdown(k);
 68     int l=t[k].l,r=t[k].r;
 69     if(l==x&&y==r)
 70     {
 71         t[k].tag++;t[k].sum+=t[k].size;
 72         return;
 73     }
 74     int mid=(l+r)>>1;
 75     if(y<=mid)update(k<<1,x,y);
 76     else if(x>mid)update(k<<1|1,x,y);
 77     else {
 78         update(k<<1,x,mid);
 79         update(k<<1|1,mid+1,y);
 80     }
 81     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
 82 }
 83 void solve_update(int x,int f){
 84     while(belong[x]!=belong[f]){
 85         update(1,pl[belong[x]],pl[x]);
 86         x=fa[belong[x]];
 87     }
 88     update(1,pl[f],pl[x]);
 89 }
 90 int query(int k,int x,int y){
 91     pushdown(k);
 92     int l=t[k].l,r=t[k].r;
 93     if(l==x&&y==r)return t[k].sum;
 94     int mid=(l+r)>>1;
 95     if(y<=mid)return query(k<<1,x,y);
 96     else if(x>mid)return query(k<<1|1,x,y);
 97     else return query(k<<1,x,mid)+query(k<<1|1,mid+1,y);
 98 }
 99 int solve_query(int x,int f)
100 {
101     int sum=0;
102     while(belong[x]!=belong[f])
103     {
104         sum+=query(1,pl[belong[x]],pl[x]);
105         sum%=mod;
106         x=fa[belong[x]];
107     }
108     sum+=query(1,pl[f],pl[x]);sum%=mod;
109     return sum;
110 }
111 int main()
112 {
113     bin[0]=1;for(int i=1;i<20;i++)bin[i]=(bin[i-1]<<1);
114     n=read();m=read();
115     for(int i=1;i<n;i++)
116     {
117         int x=read();insert(x,i);
118     }
119     int tot=0;
120     for(int i=1;i<=m;i++)
121     {
122         int l=read(),r=read();
123         q[i].z=read();
124         a[++tot].p=l-1;a[tot].num=i;a[tot].flag=0;
125         a[++tot].p=r;a[tot].num=i;a[tot].flag=1;
126     }
127     build(1,1,n);
128     sort(a+1,a+tot+1);
129     dfs1(0);dfs2(0,0);
130     int now=-1;
131     for(int i=1;i<=tot;i++)
132     {
133         while(now<a[i].p)
134         {
135             now++;
136             solve_update(now,0);
137         }
138         int t=a[i].num;
139         if(!a[i].flag)q[t].ans1=solve_query(q[t].z,0);
140         else q[t].ans2=solve_query(q[t].z,0);
141     }
142     for(int i=1;i<=m;i++)
143     printf("%d\n",(q[i].ans2-q[i].ans1+mod)%mod);
144     return 0;
145 }
想看否?

 

 

 

  4.BZOJ2243 SDOI2011 染色

  大致就是树链剖分+线段树(染色合并,01串覆盖的升级),非常之水,上代码。

CODE:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<stack>
  4 #include<queue>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<cmath>
  9 #define inf 0x3f3f3f3f
 10 #define ll long long
 11 #define maxn 300005
 12 #define lson u<<1,l,mid
 13 #define rson u<<1|1,mid+1,r 
 14 using namespace std;
 15 int    top[maxn],fa[maxn],tid[maxn],dep[maxn],val[maxn],dis[maxn],head[maxn],q[maxn],cov[maxn],pre[maxn],son[maxn],www[maxn],size[maxn],n,m,k=1,tot;
 16 struct edge{
 17     int v,next,w;
 18 }e[2*maxn];
 19 
 20 struct post{
 21     int len,a,b;
 22 }p[maxn];
 23 void adde(int u,int v,int w){
 24     e[k].v=v;
 25     e[k].w=w;
 26     e[k].next=head[u];
 27     head[u]=k++;
 28 }
 29 
 30 bool cmp(post a,post b){
 31     return a.len<b.len;
 32 }
 33 void dfs1(int u,int pre,int Dis){
 34     size[u]=1;
 35     dep[u]=dep[pre]+1;
 36     dis[u]=Dis;
 37     fa[u]=pre;
 38     int smax=0;
 39     for(int i=head[u];i;i=e[i].next){
 40         int v=e[i].v;
 41         if(v==pre)continue;
 42         www[v]=e[i].w;
 43         dfs1(v,u,Dis+e[i].w);
 44         size[u]+=size[v];
 45         if(size[v]>smax){
 46             smax=size[v];
 47             son[u]=v;
 48         }
 49     }
 50 }
 51 
 52 void dfs2(int u,int tt){
 53     tid[u]=++tot;
 54     top[u]=tt;
 55     val[tot]=www[u];
 56     if(son[u])dfs2(son[u],tt);
 57     for(int i=head[u];i;i=e[i].next){
 58         int v=e[i].v;
 59         if(v==fa[u]||v==son[u])continue;
 60         dfs2(v,v);
 61     }
 62 }
 63 
 64 int lca(int a,int b){
 65     int ta=top[a],tb=top[b];
 66     while(ta!=tb){
 67         if(dep[ta]<dep[tb]){
 68             swap(ta,tb);
 69             swap(a,b);
 70         }
 71         a=fa[ta];
 72         ta=top[a];
 73     }
 74     if(dep[a]<dep[b])return a;
 75     return b;
 76 }
 77 
 78 void pave(int u,int v){
 79     int tu=top[u],tv=top[v];
 80     while(tu!=tv){
 81         if(dep[tu]<dep[tv]){
 82             swap(u,v);swap(tu,tv);
 83         }
 84         cov[tid[tu]]++;cov[tid[u]+1]--;
 85         u=fa[tu];
 86         tu=top[u];
 87     }
 88     if(dep[u]>dep[v])swap(u,v);
 89     cov[tid[u]+1]++;
 90     cov[tid[v]+1]--;
 91 }
 92 bool check(int x){
 93     int sd,all=0,fail;
 94     for(int i=1;i<=m;i++){if(p[i].len>x){sd=i;fail=m-i+1;break;}}
 95     if(q[fail])return q[fail]+x>=p[m].len;
 96     for(int i=1;i<=tot;i++)cov[i]=0;
 97     for(int i=sd;i<=m;i++)pave(p[i].a,p[i].b);
 98     for(int i=1;i<=tot;i++){
 99         all+=cov[i];
100         if(all==fail)q[fail]=max(q[fail],val[i]);
101     }
102     return q[fail]+x>=p[m].len;
103 }
104 int main(){
105     scanf("%d%d",&n,&m);
106     int big=0;
107     for(int i=1;i<n;i++){
108         int a,b,c;
109         scanf("%d%d%d",&a,&b,&c);
110         adde(a,b,c);
111         adde(b,a,c);
112     }
113     dfs1(1,0,0);
114     dfs2(1,1);
115     for(int i=1;i<=m;i++){
116         int a,b;
117         scanf("%d%d",&a,&b);
118         p[i].a=a;p[i].b=b;
119         p[i].len=dis[a]+dis[b]-2*dis[(lca(a,b))];
120         big=max(big,p[i].len);
121     }sort(p+1,p+1+m,cmp);
122     int l=0,r=big;
123     while(l<r){
124         int mid=(l+r)>>1;
125         if(check(mid))r=mid;
126         else l=mid+1;
127     }
128     printf("%d",r);
129     return 0;
130 }
想看否?

 

   5.BZOJ2819 Nim

  妈蛋。。还搞上了博弈论,,于是 y水j老师花20min讲完了博弈论。。桑心0.0

  大致思路:

  树链剖分+线段树/树状数组+博弈论

   其实只要你懂博弈论这个题还是非常简单的(博弈论自己网上学),使用XOR可轻松搞定,每堆石子的个数为x,它的sg值也为x,直接^就行,是不是炒鸡简单?

  至于树链剖分,其实是快速查找路径(u->v),用一个线段树直接搞出每个区间的XOR值就行了23333此题就如此地水过了。

  还有就是,由于只涉及到单点修改和区间查询 ,聪明的召唤师可直接使用lowbit树状数组,秀了我一脸,懵逼ing……

  PS:不要以为之输入 Q和C 你就可以用scanf读入单个字符判断操作

  老夫就是被这个东西祸害了好久

  原因:你读入数字后还有一个回车  char c;scanf("%c",&c)后会读入一个空格,然而水水的样例还是过,这就有点坑人

  处理方法

      一:读入字符串 (scanf读入字符串会自动省略 "空格"和"回车")
  二:scanf(" %c",&c) %c前的空格千万不能省去否则就会读入 "回车" 导致程序错误

 

CODE:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<queue>
  7 #define lson u<<1,l,mid
  8 #define rson u<<1|1,mid+1,r
  9 #define N 500005
 10 using namespace std;
 11 int val[N],id[N],top[N],tid[N],dep[N],siz[N],fa[N],son[N],head[N],n,m,k=1,tot;
 12 struct edge{int v,next;}e[2*N];
 13 struct tree{int l,r,sum;}t[4*N];
 14 int read(){
 15     char c;int x=0;c=getchar();
 16     while(c>'9'||c<'0')c=getchar();
 17     while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
 18     return x;
 19 }
 20 
 21 void adde(int u,int v){
 22     e[k].v=v;
 23     e[k].next=head[u];
 24     head[u]=k++;
 25 }
 26 
 27 
 28 void dfs1(int u,int pre){
 29     siz[u]=1;
 30     fa[u]=pre;
 31     dep[u]=dep[pre]+1;
 32     for(int i=head[u];i;i=e[i].next){
 33         int v=e[i].v;
 34         if(v==pre)continue;
 35         dfs1(v,u);
 36         siz[u]+=siz[v];
 37         if(siz[v]>siz[son[u]])son[u]=v;
 38     }
 39 }
 40 
 41 void dfs2(int u,int tt){
 42     tid[u]=++tot;
 43     top[u]=tt;
 44     id[tot]=u;
 45     if(son[u])dfs2(son[u],tt);
 46     for(int i=head[u];i;i=e[i].next){
 47         int v=e[i].v;
 48         if(v==fa[u]||v==son[u])continue;
 49         dfs2(v,v);
 50     }
 51 }
 52 
 53 void pushup(int u){
 54     t[u].sum=t[u<<1].sum^t[u<<1|1].sum;
 55 }
 56 
 57 void build(int u,int l,int r){
 58     t[u].l=l;
 59     t[u].r=r;
 60     if(l==r){
 61         t[u].sum=val[id[l]];
 62         return;
 63     }
 64     int mid=(l+r)>>1;
 65     build(lson);
 66     build(rson);
 67     pushup(u);
 68 }
 69 
 70 void update(int u,int pos,int ch){
 71     if(t[u].l==t[u].r){
 72         t[u].sum=ch;
 73         return;
 74     }
 75     int mid=(t[u].l+t[u].r)>>1;
 76     if(pos<=mid)update(u<<1,pos,ch);
 77     else update(u<<1|1,pos,ch);
 78     pushup(u);
 79 }
 80 
 81 int query(int u,int l,int r){
 82     if(t[u].l==l&&t[u].r==r)return t[u].sum;
 83     int mid=(t[u].l+t[u].r)>>1;
 84     if(r<=mid)return query(u<<1,l,r);
 85     if(l>mid)return query(u<<1|1,l,r);
 86     return query(u<<1,l,mid)^query(u<<1|1,mid+1,r);
 87 }
 88 
 89 bool fuck(int u,int v){
 90     int ans=0;
 91     while(top[u]!=top[v]){
 92         if(dep[top[u]]<dep[top[v]])swap(u,v);
 93         ans^=query(1,tid[top[u]],tid[u]);
 94         u=fa[top[u]];
 95     }
 96     if(u==v)return ans^val[u];
 97     if(dep[u]>dep[v])swap(u,v);
 98     ans^=query(1,tid[u],tid[v]);
 99     return ans;
100 }
101 
102 int main(){
103     n=read();
104     for(int i=1;i<=n;i++)val[i]=read();int a,b;
105     for(int i=1;i<n;i++)a=read(),b=read(),adde(a,b),adde(b,a);
106     dfs1(1,0);dfs2(1,1);build(1,1,tot);m=read();
107     for(int i=1;i<=m;i++){
108         char s[3];
109         scanf("%s",&s);
110         a=read();b=read();
111         if(s[0]=='Q')fuck(a,b)?puts("Yes"):puts("No");
112         else val[a]=b,update(1,tid[a],b);
113     }
114     return 0;
115 }
直接给你看了,,

 

  6.BZOJ4034 HAOI2015 树上操作

  这个题非常之水,我都懒得写它,吐槽一下,作为省选怎能这样??

  首先是树链剖分可以做,加一个dfs序(或用size数组表示儿子节点总数,对应到链上表示子树)来修改自己的子树。

  听可爱的lg鸡小盆友说此题甚至可以不用树链剖分,直接dfs序+线段树。。

  代码网上直接抄的,看不看无所谓。

CODE:

  1 Description
  2  有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
  3 操作,分为三种:
  4 操作 1 :把某个节点 x 的点权增加 a 。
  5 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  6 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
  7 Input
  8  第一行包含两个整数 N, M 。表示点数和操作数。
  9 接下来一行 N 个整数,表示树中节点的初始权值。
 10 接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
 11 再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
 12 作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
 13 Output
 14  对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
 15 Sample Input
 16 5 5
 17 
 18 1 2 3 4 5
 19 
 20 1 2
 21 
 22 1 4
 23 
 24 2 3
 25 
 26 2 5
 27 
 28 3 3
 29 
 30 1 2 1
 31 
 32 3 5
 33 
 34 2 1 2
 35 
 36 3 3
 37 Sample Output
 38 6
 39 
 40 9
 41 
 42 13
 43 
 44 HINT
 45  对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
 46 
 47 会超过 10^6 48 题解:树链剖分裸题,支持点修改,链查询,子树修改,子树查询。
 49 [html] view plain copy 在CODE上查看代码片派生到我的代码片
 50 #include<iostream>  
 51 #include<cstdio>  
 52 #include<cstring>  
 53 #include<algorithm>  
 54 using namespace std;  
 55 const int N=100100;  
 56 int point[N],next[N*4],belong[N],siz[N],son[N],pos[N],deep[N];  
 57 int n,m,tot=1,num=0,fa[N];  
 58 long long tr[N*4],de[N*4],r[N];  
 59 bool use[N];  
 60 struct S{  
 61     int st,en;  
 62 }aa[N*4];  
 63 inline void add(int x,int y)  
 64 {  
 65     tot+=1;next[tot]=point[x];point[x]=tot;  
 66     aa[tot].st=x;aa[tot].en=y;  
 67     tot+=1;next[tot]=point[y];point[y]=tot;  
 68     aa[tot].st=y;aa[tot].en=x;  
 69 }  
 70 inline void dfs_1(int x)  
 71 {  
 72     int i;  
 73     siz[x]=1;  
 74     use[x]=false;  
 75     for(i=point[x];i;i=next[i])  
 76       if(use[aa[i].en]){  
 77         deep[aa[i].en]=deep[x]+1;  
 78         fa[aa[i].en]=x;  
 79         dfs_1(aa[i].en);  
 80         siz[x]+=siz[aa[i].en];  
 81       }  
 82 }  
 83 inline void dfs_2(int x,int y)  
 84 {  
 85     int i,k=0;  
 86     num+=1;  
 87     pos[x]=son[x]=num;  
 88     belong[x]=y;  
 89     for(i=point[x];i;i=next[i])  
 90       if(deep[x]<deep[aa[i].en]&&siz[k]<siz[aa[i].en])  
 91         k=aa[i].en;  
 92     if(k==0) return ;  
 93     dfs_2(k,y);son[x]=max(son[k],son[x]);  
 94     for(i=point[x];i;i=next[i])  
 95       if(deep[x]<deep[aa[i].en]&&k!=aa[i].en){  
 96         dfs_2(aa[i].en,aa[i].en);  
 97         son[x]=max(son[x],son[aa[i].en]);  
 98     }  
 99 }  
100 #define mid (l+r)/2  
101 #define L k<<1,l,mid  
102 #define R k<<1|1,mid+1,r  
103 inline void paint(int k,int l,int r,long long z)  
104 {  
105     de[k]+=z;  
106     tr[k]+=(r-l+1)*z;  
107 }  
108 inline void pushdown(int k,int l,int r)  
109 {  
110     if(l==r) return ;  
111     paint(L,de[k]);  
112     paint(R,de[k]);  
113     de[k]=0;  
114 }  
115 inline void insert(int k,int l,int r,int x,long long y)  
116 {  
117     if(l==r&&l==x){  
118         tr[k]+=y;  
119         return ;  
120     }  
121     pushdown(k,l,r);  
122     if(x<=mid) insert(L,x,y);  
123     else insert(R,x,y);  
124     tr[k]=tr[k<<1]+tr[k<<1|1];  
125 }  
126 inline void change(int k,int l,int r,int x,int y,long long z)  
127 {  
128     if(x<=l&&y>=r){  
129         paint(k,l,r,z);  
130         return ;  
131     }  
132     pushdown(k,l,r);  
133     if(x<=mid) change(L,x,y,z);  
134     if(y>mid) change(R,x,y,z);  
135     tr[k]=tr[k<<1]+tr[k<<1|1];  
136 }  
137 inline long long qurey(int k,int l,int r,int x,int y)  
138 {  
139     long long sum=0;  
140     if(x<=l&&y>=r) return tr[k];  
141     pushdown(k,l,r);  
142     if(x<=mid) sum+=qurey(L,x,y);  
143     if(y>mid) sum+=qurey(R,x,y);  
144     return sum;  
145 }  
146 inline long long ask(int x,int y)  
147 {  
148     long long sum=0;  
149     while(belong[x]!=belong[y]){  
150         sum+=qurey(1,1,n,pos[belong[x]],pos[x]);  
151         x=fa[belong[x]];  
152     }  
153     sum+=qurey(1,1,n,pos[y],pos[x]);  
154     return sum;  
155 }  
156 int main()  
157 {  
158     int i,j,x,t,root;  
159     long long y;  
160     memset(use,1,sizeof(use));  
161     scanf("%d%d",&n,&m);  
162     for(i=1;i<=n;++i) scanf("%lld",&r[i]);  
163     for(i=1;i<n;++i){  
164         scanf("%d%d",&x,&y);  
165         add(x,y);  
166     }  
167     dfs_1(1);  
168     dfs_2(1,1);  
169     for(i=1;i<=n;++i){  
170         insert(1,1,n,pos[i],r[i]);  
171         if(deep[i]==0) root=i;  
172     }  
173     while(m--){  
174         scanf("%d",&t);  
175         if(t==1||t==2){  
176             scanf("%d%lld",&x,&y);  
177             if(t==1) insert(1,1,n,pos[x],y);  
178             if(t==2) change(1,1,n,pos[x],son[x],y);  
179         }  
180         else{  
181             scanf("%d",&x);  
182             printf("%lld\n",ask(x,root));  
183         }  
184     }  
185 }  
View Code

 

至此,愉快的一天就结束了。很累很充实哈!

哈哈哈哈即使是停掉常规课学竞赛老子依然写完了生物和英语作业,屌否?

现在是22:20,可爱的lg鸡,美腻的张姐,和猥琐的lence_鸡正在CS:GO

勤奋的二哥仍然在学习KMP

我花了一个小时写完了这个博客,快哉快哉。。。

  

 

posted @ 2017-03-27 22:22  _wsy  阅读(182)  评论(2编辑  收藏  举报