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