2019.7.26 T1 树剖+双标记

Posted ljb666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019.7.26 T1 树剖+双标记相关的知识,希望对你有一定的参考价值。

题目链接

之前很久的一道题,还是写一写,这道题一眼就是树剖不用说了吧,但是它要同时支持区间赋值和加法操作,所以我们肯定需要两个标记,但是当赋值和加法标记同时下方的时候,就需要我们的细节处理,首先赋值的初始值应该赋为-1,而且下方的时候要先释放优先级高的赋值标记。区间赋值的时候,必须清空之前的加标记!当时考试的时候就是因为这样爆零了,惨痛的教训。

代码如下:

技术图片
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e6+7;
  4 const int N=1e7+7;
  5 struct seg
  6     int l,r,lazy1,lazy2;
  7     long long sum;
  8 tree[maxn*10];
  9 struct node
 10     int nxt,to;
 11 edge[maxn*2];
 12 int n,m;
 13 int a[maxn];
 14 int dep[maxn],fa[maxn],size[maxn],id[maxn],son[maxn],rev[maxn],top[maxn];
 15 bool not_zhishu[N];
 16 int prime[maxn];
 17 int Time,cnt;
 18 int head[maxn];
 19 int opt,x,y,k;
 20 int st,ed;
 21 int jmr;
 22 bool flag;
 23 inline void Euler()
 24     for( register int i=2;i<=10000000;i++)
 25         if(!not_zhishu[i]) prime[++prime[0]] = i;
 26         for(register int j=1;j<=prime[0]&&i*prime[j]<=10000000;j++)
 27             not_zhishu[i*prime[j]]=true;
 28             if(i%prime[j]==0) break;
 29         
 30     
 31 
 32 inline void add(int u,int v)
 33     edge[++cnt].nxt=head[u];
 34     edge[cnt].to=v;
 35     head[u]=cnt;
 36 
 37 inline void dfs1(int x,int f)
 38     dep[x]=dep[f]+1;
 39     fa[x]=f;
 40     size[x]=1;
 41     int maxson=-1;
 42     for(int i=head[x];i;i=edge[i].nxt)
 43         int v=edge[i].to;
 44         if(v==f) continue;
 45         dfs1(v,x);
 46         size[x]+=size[v];
 47         if(size[v]>maxson||son[x]==-1)
 48             maxson=size[v];
 49             son[x]=v;
 50         
 51     
 52 
 53 inline void dfs2(int x,int topf)
 54     top[x]=topf;
 55     id[x]=++Time;
 56     rev[id[x]]=x;
 57     if(son[x]==-1) return;
 58     dfs2(son[x],topf);
 59     for(int i=head[x];i;i=edge[i].nxt)
 60         int v=edge[i].to;
 61         if(v==son[x]||v==fa[x]) continue;
 62         dfs2(v,v);
 63     
 64 
 65 inline void pushup(int x)
 66     tree[x].sum=tree[x*2].sum+tree[x*2+1].sum;
 67 
 68 inline void pushdown(int x)
 69     if(tree[x].lazy2!=-1)
 70         tree[x*2].sum=tree[x].lazy2*(tree[x*2].r-tree[x*2].l+1);
 71         tree[x*2+1].sum=tree[x].lazy2*(tree[x*2+1].r-tree[x*2+1].l+1);
 72         tree[x*2].lazy2=tree[x].lazy2;
 73         tree[x*2+1].lazy2=tree[x].lazy2;
 74         tree[x].lazy2=-1;
 75         tree[x*2+1].lazy1=tree[x*2].lazy1=0;
 76     
 77     if(tree[x].lazy1)
 78         tree[x*2].sum+=tree[x].lazy1*(tree[x*2].r-tree[x*2].l+1);
 79         tree[x*2+1].sum+=tree[x].lazy1*(tree[x*2+1].r-tree[x*2+1].l+1);
 80         tree[x*2].lazy1+=tree[x].lazy1;
 81         tree[x*2+1].lazy1+=tree[x].lazy1;
 82         tree[x].lazy1=0;
 83     
 84 
 85 inline void build(int now,int l,int r)
 86     tree[now].l=l;
 87     tree[now].r=r;
 88     tree[now].lazy1=0;
 89     tree[now].lazy2=-1;
 90     if(l==r)
 91         tree[now].sum=a[rev[l]];
 92         return;
 93     
 94     int mid=(l+r)>>1;
 95     build(now*2,l,mid);
 96     build(now*2+1,mid+1,r);
 97     pushup(now);
 98 
 99 inline void modify1(int now,int l,int r,int v)
100     if(tree[now].l>=l&&tree[now].r<=r)
101         tree[now].sum+=(tree[now].r-tree[now].l+1)*v;
102         tree[now].lazy1+=v;
103         return;
104     
105     pushdown(now);
106     int mid=(tree[now].l+tree[now].r)>>1;
107     if(l<=mid) modify1(now*2,l,r,v);
108     if(r>mid) modify1(now*2+1,l,r,v);
109     pushup(now);
110 
111 inline void modify2(int now,int l,int r,int v)
112     if(tree[now].l>=l&&tree[now].r<=r)
113         tree[now].lazy2=v;
114         tree[now].sum=(tree[now].r-tree[now].l+1)*v;
115         tree[now].lazy1=0;
116         return;
117     
118     pushdown(now);
119     int mid=(tree[now].l+tree[now].r)>>1;
120     if(l<=mid) modify2(now*2,l,r,v);
121     if(r>mid) modify2(now*2+1,l,r,v);
122     pushup(now);
123 
124 inline int query(int now,int l,int r)
125     if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum;
126     int mid=(tree[now].l+tree[now].r)>>1;
127     pushdown(now);
128     int val=0;
129     if(l<=mid) val+=query(now*2,l,r);
130     if(r>mid) val+=query(now*2+1,l,r);
131     return val;
132 
133 inline void link1(int x,int y,int v)
134     while(top[x]!=top[y])
135         if(dep[top[x]]<dep[top[y]]) swap(x,y);
136         modify1(1,id[top[x]],id[x],v);
137         x=fa[top[x]];
138     
139     if(dep[x]<dep[y]) swap(x,y);
140     modify1(1,id[y],id[x],v);
141 
142 inline void link2(int x,int y,int v)
143     while(top[x]!=top[y])
144         if(dep[top[x]]<dep[top[y]]) swap(x,y);
145         modify2(1,id[top[x]],id[x],v);
146         x=fa[top[x]];
147     
148     if(dep[x]<dep[y]) swap(x,y);
149     modify2(1,id[y],id[x],v);
150 
151 inline void linkquery(int x,int y)
152     int ans=0;
153     while(top[x]!=top[y])
154         if(dep[top[x]]<dep[top[y]]) swap(x,y);
155         ans+=query(1,id[top[x]],id[x]);
156         x=fa[top[x]];
157     
158     if(dep[x]<dep[y]) swap(x,y);
159     ans+=query(1,id[y],id[x]);
160     if(ans<=3)printf("TANOSHI\n");return;
161     if(ans%2==0)printf("SUGOI\n");return;
162     int tmp=ans-2;
163     if(not_zhishu[tmp])printf("TANOSHI\n");return;
164     elseprintf("SUGOI\n");return;
165 
166 int main()
167 //    freopen("japari.in","r",stdin);
168 //    freopen("japari.out","w",stdout); 
169     memset(son,-1,sizeof(son));
170     Euler();
171     scanf("%d%d",&n,&m);
172     for(register int i=1;i<=n;i++)
173         scanf("%d",&a[i]);
174      
175     for(register int i=1;i<n;i++)
176         scanf("%d%d",&st,&ed);
177         add(st,ed);add(ed,st);
178     
179     dfs1(1,0);
180     dfs2(1,1);
181     build(1,1,n);
182     for(register int i=1;i<=m;i++)
183         scanf("%d",&opt);
184         if(opt==1)
185             scanf("%d%d%d",&x,&y,&k);
186             link1(x,y,k);
187         
188         else if(opt==2)
189             scanf("%d%d%d",&x,&y,&k);
190             link2(x,y,k);
191         
192         else
193             scanf("%d%d",&x,&y);
194             linkquery(x,y);
195          
196     
197     return 0;
198 
View Code

 

以上是关于2019.7.26 T1 树剖+双标记的主要内容,如果未能解决你的问题,请参考以下文章

网页制作常用标签

bzoj 维护序列seq(双标记线段树)

bzoj 1798 双标记区间修改线段树

值得一做》关于双标记线段树两三事BZOJ 1798 (NORMAL-)

线段树中区间加减和区间覆盖的双标记问题

传单地图双标问题