动态最大带权独立集
(还有一个是全局平衡二叉树的解法,还没学)
1 #include"bits/stdc++.h" 2 3 using namespace std; 4 const int inf = 1e8; 5 int n,m; 6 int v[100005]; 7 const int nn = 1e5+10; 8 9 int link[nn<<1],son[nn<<1],nxt[nn<<1]; 10 int tot_; 11 int top[nn],deep[nn],wson[nn],fa[nn],size[nn],bot[nn]; 12 int f[nn][2]; 13 int dfn[nn]; 14 int id[nn]; 15 int tot; 16 17 18 struct Mat 19 { 20 int l,r,a[3][3]; 21 Mat(int a1=0,int a2=0,int d1=0,int d2=0,int d3=0,int d4=0) 22 { 23 l=a1,r=a2; 24 a[1][1]=d1,a[1][2] = d2; 25 a[2][1] = d3,a[2][2] = d4; 26 } 27 28 29 }tr[nn<<2]; 30 31 Mat operator*(const Mat a,const Mat b) 32 { 33 Mat re=Mat(2,2); 34 35 36 re.a[1][1] = max(a.a[1][1]+b.a[1][1],a.a[1][2]+b.a[2][1]); 37 re.a[1][2] = max(a.a[1][1]+b.a[1][2],a.a[1][2]+b.a[2][2]); 38 39 re.a[2][1] = max(a.a[2][1]+b.a[1][1],a.a[2][2]+b.a[2][1]); 40 re.a[2][2] = max(a.a[2][1]+b.a[1][2],a.a[2][2]+b.a[2][2]); // 手动 41 42 return re; 43 } 44 45 inline int rd(){ 46 int x=0;char c=getchar();int neg=1; 47 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 48 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 49 return x*neg; 50 } 51 52 inline void adde(int x,int y) 53 { 54 ++tot_; 55 nxt[tot_] = link[x]; 56 link[x] = tot_; 57 son[tot_] = y; 58 } 59 60 void dfs1(int x,int ff,int dd) 61 { 62 fa[x] =ff; 63 size[x] =1; 64 f[x][1] = v[x]; 65 f[x][0] = 0; 66 67 for (int i=link[x];i;i=nxt[i]) 68 { 69 int so = son[i]; 70 if (so==ff) continue; 71 dfs1(so,x,dd+1); 72 size[x] += size[so]; 73 if (size[wson[x]]<size[so]) wson[x] = so; 74 f[x][1] += f[so][0]; 75 f[x][0] += max(f[so][1],f[so][0]); 76 77 78 } 79 80 } 81 82 void dfs2(int x,int t) 83 { 84 top[x] = t; 85 dfn[x] = ++tot; 86 id[tot] =x; 87 88 if (!wson[x]) bot[top[x]] = x;//不要写成t 89 else dfs2(wson[x],t); 90 91 for ( int i=link[x];i;i=nxt[i]) 92 { 93 int so =son[i]; 94 if (so==wson[x]||so==fa[x]) continue; 95 dfs2(so,so); 96 } 97 } 98 99 100 inline void change(int rt,int l,int r,int pos,int a,int b) 101 { 102 if (l==r) 103 { 104 tr[rt].a[1][1]+=a; tr[rt].a[2][1]+=a; 105 tr[rt].a[1][2]+=b; 106 return ; 107 } 108 109 int mid = l+r>>1; 110 if (pos<=mid) change(rt<<1,l,mid,pos,a,b); 111 else change(rt<<1|1,mid+1,r,pos,a,b); 112 tr[rt]=tr[rt<<1|1]*tr[rt<<1];//注意顺序 113 } 114 115 116 inline Mat query(int p,int l,int r,int x,int y){ 117 if(x<=l&&r<=y) 118 { 119 return tr[p]; 120 } 121 else{ 122 int m=l+r>>1;Mat re=Mat(2,2,0,-inf,-inf,0); 123 if(y>=m+1) re=re*query(p<<1|1,m+1,r,x,y); 124 if(x<=m) re=re*query(p<<1,l,m,x,y); 125 return re; 126 } 127 } 128 129 130 inline void update(int x,int y) 131 { 132 Mat nw,od; 133 int a,b; 134 while (x) 135 { if (y) a=0,b=y,y=0; 136 else a=max(nw.a[1][2],nw.a[1][1]) - max(od.a[1][2],od.a[1][1]), 137 b = nw.a[1][1] - od.a[1][1]; 138 139 od = query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]); 140 change(1,1,n,dfn[x],a,b); 141 nw = query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]); 142 x=fa[top[x]]; 143 } 144 145 printf("%d ",max(nw.a[1][1],nw.a[1][2])); 146 } 147 148 void build (int rt,int l,int r) 149 { 150 if (l==r) 151 { 152 int zhi = id[l]; 153 int a = f[zhi][0] - max(f[wson[zhi]][0],f[wson[zhi]][1]); 154 int b = f[zhi][1] - f[wson[zhi]][0]; 155 tr[rt] = Mat(2,2,a,b,a,-1e8); 156 return ; 157 } 158 159 int mid = l+r>>1; 160 build(rt<<1,l,mid); 161 build(rt<<1|1,mid+1,r); 162 tr[rt]=tr[rt<<1|1]*tr[rt<<1]; 163 } 164 165 int main() 166 { 167 n=rd(); m = rd(); 168 for ( int i=1;i<=n;i++) v[i] = rd(); 169 170 for ( int i =1;i<n;i++) 171 { 172 int a,b;a=rd(); b = rd(); 173 adde(a,b); 174 adde(b,a); 175 } 176 dfs1(1,0,1); 177 dfs2(1,1); 178 179 build(1,1,n); 180 //puts("$%^&*"); 181 182 for ( int i=1;i<=m;i++) 183 184 { 185 // puts("123f"); 186 int a,b;a=rd(); b=rd(); 187 188 update(a,b-v[a]); 189 // puts("213"); 190 v[a] =b; 191 } 192 return 0; 193 }