1. 程式人生 > >洛谷 P3676 小清新資料結構題

洛谷 P3676 小清新資料結構題

https://www.luogu.org/problemnew/show/P3676

這題被我當成動態dp去做了,碼了4k,搞了一個換根的動態dp

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 using namespace std;
  5 typedef long long ll;
  6 struct E
  7 {
  8     int to,nxt;
  9 }e[400011];
 10 int f1[200011],ne;
11 struct P1 12 { 13 int len;ll a,b,c,d,e,f; 14 //長度,(點權)和,字尾和之和,字尾和的平方之和,(答案)和 15 //字首和之和,字首和的平方之和 16 }; 17 struct P2 18 { 19 ll a,b; 20 //點權和,答案和 21 }; 22 ll a[200101]; 23 int sz[200101],hson[200101],ff[200101]; 24 int b[200101],pl[200101]; 25 int n,m; 26 inline void merge(P1 &c,const
P1 &a,const P1 &b) 27 { 28 c.len=a.len+b.len; 29 c.a=a.a+b.a; 30 c.b=b.b+a.b+b.a*a.len; 31 c.c=b.c+b.a*b.a*a.len+2*a.b*b.a+a.c; 32 c.d=a.d+b.d; 33 c.e=a.e+b.e+a.a*b.len; 34 c.f=a.f+a.a*a.a*b.len+2*b.e*a.a+b.f; 35 } 36 inline void initnode(P1 &c,const
P2 &a) 37 { 38 c.len=1;c.a=c.b=c.e=a.a;c.c=c.f=a.a*a.a;c.d=a.b; 39 } 40 namespace S 41 { 42 #define lc (num<<1) 43 #define rc (num<<1|1) 44 P1 d[800101]; 45 inline void upd(int num){merge(d[num],d[lc],d[rc]);} 46 P1 x;int L; 47 void _setx(int l,int r,int num) 48 { 49 if(l==r) 50 { 51 d[num]=x; 52 return; 53 } 54 int mid=(l+r)>>1; 55 if(L<=mid) _setx(l,mid,lc); 56 else _setx(mid+1,r,rc); 57 upd(num); 58 } 59 P1 getx(int L,int R,int l,int r,int num) 60 { 61 if(L<=l&&r<=R) return d[num]; 62 int mid=(l+r)>>1; 63 if(L<=mid&&mid<R) 64 { 65 P1 x; 66 merge(x,getx(L,R,l,mid,lc),getx(L,R,mid+1,r,rc)); 67 return x; 68 } 69 else if(L<=mid) 70 return getx(L,R,l,mid,lc); 71 else if(mid<R) 72 return getx(L,R,mid+1,r,rc); 73 else 74 exit(-1); 75 } 76 } 77 void dfs1(int u,int fa) 78 { 79 sz[u]=1; 80 for(int v,k=f1[u];k;k=e[k].nxt) 81 if(e[k].to!=fa) 82 { 83 v=e[k].to; 84 ff[v]=u; 85 dfs1(v,u); 86 sz[u]+=sz[v]; 87 if(sz[v]>sz[hson[u]]) hson[u]=v; 88 } 89 } 90 P2 d1[200101];//d1[i]維護i節點及其輕兒子的貢獻 91 P2 d2[200101];//d2[i]維護i節點(是重鏈頂)所在重鏈的值 92 int tp[200101],dwn[200101];//鏈頂,鏈底 93 inline void updd1(int x) 94 { 95 initnode(S::x,d1[x]);S::L=pl[x];S::_setx(1,n,1); 96 } 97 void dfs2(int u,int fa) 98 { 99 d1[u].a=a[u]; 100 b[++b[0]]=u;pl[u]=b[0]; 101 tp[u]=(u==hson[fa])?tp[fa]:u; 102 if(hson[u]) dfs2(hson[u],u); 103 dwn[u]=hson[u]?dwn[hson[u]]:u; 104 int v,k; 105 for(k=f1[u];k;k=e[k].nxt) 106 if(e[k].to!=fa&&e[k].to!=hson[u]) 107 { 108 v=e[k].to; 109 dfs2(v,u); 110 d1[u].b+=d2[v].b; 111 d1[u].a+=d2[v].a; 112 } 113 updd1(u); 114 if(u==tp[u]) 115 { 116 P1 t=S::getx(pl[u],pl[dwn[u]],1,n,1); 117 d2[u].a=t.a;d2[u].b=t.d+t.c; 118 } 119 } 120 inline ll getsize(int x) 121 { 122 return S::getx(pl[x],pl[dwn[x]],1,n,1).a; 123 } 124 int main() 125 { 126 int i,x,y,idx;ll z,ans,szall;P1 t; 127 scanf("%d%d",&n,&m); 128 for(i=1;i<n;++i) 129 { 130 scanf("%d%d",&x,&y); 131 e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne; 132 e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne; 133 } 134 for(i=1;i<=n;++i) scanf("%lld",a+i); 135 dfs1(1,0); 136 dfs2(1,0); 137 while(m--) 138 { 139 scanf("%d",&idx); 140 if(idx==1) 141 { 142 scanf("%d%lld",&x,&z); 143 d1[x].a-=a[x];a[x]=z;d1[x].a+=z; 144 while(x) 145 { 146 updd1(x); 147 x=tp[x];y=ff[x]; 148 t=S::getx(pl[x],pl[dwn[x]],1,n,1); 149 d1[y].a-=d2[x].a;d1[y].b-=d2[x].b; 150 d2[x].a=t.a;d2[x].b=t.d+t.c; 151 d1[y].a+=d2[x].a;d1[y].b+=d2[x].b; 152 x=y; 153 } 154 //printf("3t%d\n",d2[1].b); 155 } 156 else 157 { 158 scanf("%d",&x); 159 ans=d2[1].b; 160 szall=getsize(1); 161 if(x!=tp[x]) 162 { 163 y=tp[x]; 164 z=d1[y].a; 165 d1[y].a+=szall-getsize(y); 166 updd1(y); 167 if(y!=dwn[y]) 168 { 169 t=S::getx(pl[y]+1,pl[dwn[y]],1,n,1); 170 ans-=t.c; 171 } 172 if(x!=dwn[y]) 173 { 174 t=S::getx(pl[x]+1,pl[dwn[y]],1,n,1); 175 ans+=t.c; 176 } 177 t=S::getx(pl[y],pl[x]-1,1,n,1); 178 ans+=t.f; 179 d1[y].a=z; 180 updd1(y); 181 x=y; 182 } 183 while(x!=1) 184 { 185 y=ff[x]; 186 z=getsize(x); 187 ans-=z*z; 188 z=szall-z; 189 ans+=z*z; 190 x=y; 191 if(x!=tp[x]) 192 { 193 y=tp[x]; 194 z=d1[y].a; 195 d1[y].a+=szall-getsize(y); 196 updd1(y); 197 if(y!=dwn[y]) 198 { 199 t=S::getx(pl[y]+1,pl[dwn[y]],1,n,1); 200 ans-=t.c; 201 } 202 if(x!=dwn[y]) 203 { 204 t=S::getx(pl[x]+1,pl[dwn[y]],1,n,1); 205 ans+=t.c; 206 } 207 t=S::getx(pl[y],pl[x]-1,1,n,1); 208 ans+=t.f; 209 d1[y].a=z; 210 updd1(y); 211 x=y; 212 } 213 } 214 printf("%lld\n",ans); 215 } 216 } 217 return 0; 218 }
View Code

碼完一看題解,???好像畫風不太對??

所以還是無視上面那個程式碼吧...

正常得多的做法:

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 typedef long long ll;
  5 struct E
  6 {
  7     int to,nxt;
  8 }e[400011];
  9 int f1[200011],ne;
 10 int n,m;
 11 struct S
 12 {
 13 #define lowbit(x) ((x)&(-x))
 14     ll d1[200011],d2[200011];
 15     void _add(int p,ll x,ll *d)
 16     {
 17         for(;p<=n;p+=lowbit(p))
 18             d[p]+=x;
 19     }
 20     ll _sum(int p,ll *d)
 21     {
 22         ll ans=0;
 23         for(;p>0;p-=lowbit(p))
 24             ans+=d[p];
 25         return ans;
 26     }
 27     void add(int l,int r,ll x)
 28     {
 29         _add(l,x,d1);
 30         _add(r+1,-x,d1);
 31         _add(l,x*l,d2);
 32         _add(r+1,-x*(r+1),d2);
 33     }
 34     ll sum(int l,int r)
 35     {
 36         return (r+1)*_sum(r,d1)-_sum(r,d2)
 37             -l*_sum(l-1,d1)+_sum(l-1,d2);
 38     }
 39 }s1;
 40 int b[200011],pl[200011];
 41 ll a[200011],a2[200011];
 42 int sz[200011],hson[200011],tp[200011];
 43 ll dep[200011];
 44 int ff[200011];
 45 void dfs1(int u,int fa)
 46 {
 47     sz[u]=1;
 48     for(int k=f1[u];k;k=e[k].nxt)
 49         if(e[k].to!=fa)
 50         {
 51             ff[e[k].to]=u;
 52             dep[e[k].to]=dep[u]+1;
 53             dfs1(e[k].to,u);
 54             sz[u]+=sz[e[k].to];
 55             if(sz[e[k].to]>sz[hson[u]])    hson[u]=e[k].to;
 56         }
 57 }
 58 void dfs2(int u,int fa)
 59 {
 60     b[++b[0]]=u;pl[u]=b[0];
 61     tp[u]=u==hson[fa]?tp[fa]:u;
 62     a2[u]=a[u];
 63     if(hson[u])
 64     {
 65         dfs2(hson[u],u);
 66         a2[u]+=a2[hson[u]];
 67     }
 68     for(int k=f1[u];k;k=e[k].nxt)
 69         if(e[k].to!=fa&&e[k].to!=hson[u])
 70         {
 71             dfs2(e[k].to,u);
 72             a2[u]+=a2[e[k].to];
 73         }
 74 }
 75 inline ll gsum1(int x)//x到1的路徑和
 76 {
 77     int y;ll an=0;
 78     for(;x;x=ff[y])
 79     {
 80         y=tp[x];
 81         an+=s1.sum(pl[y],pl[x]);
 82     }
 83     return an;
 84 }
 85 inline void add1(int x,ll z)//x到1加上z
 86 {
 87     int y;
 88     for(;x;x=ff[y])
 89     {
 90         y=tp[x];
 91         s1.add(pl[y],pl[x],z);
 92     }
 93 }
 94 ll anss;
 95 int main()
 96 {
 97     ll ans,z,t;
 98     int i,x,y,idx;
 99     scanf("%d%d",&n,&m);
100     for(i=1;i<n;++i)
101     {
102         scanf("%d%d",&x,&y);
103         e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;
104         e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;
105     }
106     for(i=1;i<=n;++i)
107         scanf("%lld",a+i);
108     dfs1(1,0);
109     dfs2(1,0);
110     for(i=1;i<=n;++i)
111     {
112         s1.add(pl[i],pl[i],a2[i]);
113         anss+=a2[i]*a2[i];
114     }
115     while(m--)
116     {
117         scanf("%d",&idx);
118         if(idx==1)
119         {
120             scanf("%d%lld",&x,&z);
121             z=z-a[x];a[x]+=z;
122             anss+=z*z*(dep[x]+1);
123             anss+=2*gsum1(x)*z;
124             add1(x,z);
125         }
126         else
127         {
128             scanf("%d",&x);
129             ans=anss;
130             t=gsum1(1);
131             ans+=dep[x]*t*t;
132             ans-=2*t*(gsum1(x)-t);
133             printf("%lld\n",ans);
134         }
135     }
136     return 0;
137 }
View Code