[loj3076]公园
为了方便,对题意做以下处理:
1.称"西部主题"和"科幻主题"分别为黑色和白色
2.删去题中"保证没有两条不同的道路连接同一对景点"的条件
关于题中的条件,即保证图中总存在重边、一度点或二度点(或仅剩一个点)
(具体证明参考2019年的论文,这里就省略了)
考虑对这些特殊的结构进行处理,具体如下——
对于节点$x$,将其点权$w_{x}$用一个$2\times 1$的矩阵描述,分别为$x$染黑色和白色的美观度
对于边$(x,y)$,将其边权$v_{(x,y)}$用一个$4\times 1$的矩阵描述,分别为$x$染黑色$y$染黑色、$x$染黑色$y$染白色、$x$染白色$y$染黑色和$x$染白色$y$染白色时这条边的美观度
关于重边,假设两边分别为$e_{1}$和$e_{2}$,构造边权之间的二元运算$\oplus$,使得合并后新边边权为$v_{e_{1}}\oplus v_{e_{2}}$
关于一度点,假设该点为$x$、出边为$e$、出边终点为$y$,构造点权、边权和点权之间的三元运算$\odot$(结果为点权),使得合并后新点点权为$\odot\left(w_{x},v_{e},w_{y}\right)$
关于二度点,假设该点为$x$,出边分别为$e_{1}$和$e_{2}$,构造边权、点权和边权之间的三元运算$\otimes$(结果为边权),使得合并后新边边权为$\otimes(v_{e_{1}},w_{x},v_{e_{2}})$(方向为从$e_{1}$终点指向$e_{2}$终点)
另外,注意到每一条边仅存储了一个方向,可能会导致无法合并,因此还需要一个反向操作
为了让其更形式化,构造边权的一元运算$R$,使得$R(w_{e})$为将$e$反向后的边边权
(为了让阅读更连贯,具体的构造都放在文末)
由此,可以得到一棵表达式树,树上的叶子节点存储初始的点权和边权,非叶子节点存储一种运算(上述四种之一),运算后根节点必然是点权且将两值取$\max$即为答案
类似于动态dp,将其树链剖分,问题即是要修改某个位置的值后能快速维护其重链顶端的值
提取一个类似于矩阵乘法的运算$*$,满足$A*B=C$,其中$A,B$和$C$分别是$a\times b,b\times c$和$a\times c$的矩阵,并且有$C_{i,j}=\max_{k=1}^{b}(a_{i,k}+b_{k,j})$,显然其与矩阵乘法一样满足结合律
通过这个运算,那么在这之前的四种运算中,每次运算结果都可以看作其中任意一个参与运算的变量左$*$一个矩阵(这个矩阵由剩下的参与运算的变量确定)
由此,在每个位置上记录需要左$*$的矩阵,根据$*$的结合律即可用线段树维护(注意每次要从链尾算起)
总复杂度为$o(n\log^{2}n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define M 1000005 5 #define ll long long 6 #define L (k<<1) 7 #define R (L+1) 8 #define mid (l+r>>1) 9 int n,m,V,q,x,y,num[20],op[M],v[M][3]; 10 struct matrix{ 11 int n,m; 12 ll a[4][4]; 13 bool operator != (const matrix &k)const{ 14 if ((n!=k.n)||(m!=k.m))return 1; 15 for(int i=0;i<k.n;i++) 16 for(int j=0;j<m;j++) 17 if (a[i][j]!=k.a[i][j])return 1; 18 return 0; 19 } 20 matrix(){ 21 n=m=0; 22 memset(a,-0x3f,sizeof(a)); 23 } 24 }w[M],trans[M]; 25 int read(){ 26 int x=0; 27 char c=getchar(); 28 while ((c<'0')||(c>'9'))c=getchar(); 29 while ((c>='0')&&(c<='9')){ 30 x=x*10+c-'0'; 31 c=getchar(); 32 } 33 return x; 34 } 35 void write(ll n,char c='\0'){ 36 while (n){ 37 num[++num[0]]=n%10; 38 n/=10; 39 } 40 if (!num[0])putchar('0'); 41 while (num[0])putchar(num[num[0]--]+'0'); 42 putchar(c); 43 } 44 matrix mul(matrix a,matrix b){ 45 matrix ans; 46 ans.n=a.n,ans.m=b.m; 47 for(int i=0;i<a.n;i++) 48 for(int j=0;j<a.m;j++) 49 for(int k=0;k<b.m;k++)ans.a[i][k]=max(ans.a[i][k],a.a[i][j]+b.a[j][k]); 50 return ans; 51 } 52 matrix get(int type,matrix a=matrix(),matrix b=matrix()){ 53 matrix ans; 54 if (type==1){ 55 ans.n=ans.m=4; 56 for(int i=0;i<4;i++)ans.a[i][i]=a.a[i][0]; 57 } 58 if (type==2){ 59 ans.n=ans.m=2; 60 ans.a[0][0]=a.a[0][0]+b.a[0][0]; 61 ans.a[0][1]=a.a[2][0]+b.a[0][0]; 62 ans.a[1][0]=a.a[1][0]+b.a[1][0]; 63 ans.a[1][1]=a.a[3][0]+b.a[1][0]; 64 } 65 if (type==3){ 66 ans.n=2,ans.m=4; 67 ans.a[0][0]=a.a[0][0]+b.a[0][0]; 68 ans.a[0][2]=a.a[1][0]+b.a[0][0]; 69 ans.a[1][1]=a.a[0][0]+b.a[1][0]; 70 ans.a[1][3]=a.a[1][0]+b.a[1][0]; 71 } 72 if (type==4){ 73 ans.n=ans.m=2; 74 ans.a[0][0]=max(a.a[0][0]+b.a[0][0],a.a[1][0]+b.a[2][0]); 75 ans.a[1][1]=max(a.a[0][0]+b.a[1][0],a.a[1][0]+b.a[3][0]); 76 } 77 if (type==5){ 78 ans.n=ans.m=4; 79 ans.a[0][0]=ans.a[2][1]=a.a[0][0]+b.a[0][0]; 80 ans.a[0][2]=ans.a[2][3]=a.a[1][0]+b.a[2][0]; 81 ans.a[1][0]=ans.a[3][1]=a.a[0][0]+b.a[1][0]; 82 ans.a[1][2]=ans.a[3][3]=a.a[1][0]+b.a[3][0]; 83 } 84 if (type==6){ 85 ans.n=4,ans.m=2; 86 ans.a[0][0]=a.a[0][0]+b.a[0][0]; 87 ans.a[0][1]=a.a[2][0]+b.a[2][0]; 88 ans.a[1][0]=a.a[0][0]+b.a[1][0]; 89 ans.a[1][1]=a.a[2][0]+b.a[3][0]; 90 ans.a[2][0]=a.a[1][0]+b.a[0][0]; 91 ans.a[2][1]=a.a[3][0]+b.a[2][0]; 92 ans.a[3][0]=a.a[1][0]+b.a[1][0]; 93 ans.a[3][1]=a.a[3][0]+b.a[3][0]; 94 } 95 if (type==7){ 96 ans.n=ans.m=4; 97 ans.a[0][0]=ans.a[1][1]=a.a[0][0]+b.a[0][0]; 98 ans.a[0][2]=ans.a[1][3]=a.a[2][0]+b.a[1][0]; 99 ans.a[2][0]=ans.a[3][1]=a.a[1][0]+b.a[0][0]; 100 ans.a[2][2]=ans.a[3][3]=a.a[3][0]+b.a[1][0]; 101 } 102 if (type==8){ 103 ans.n=ans.m=4; 104 ans.a[0][0]=ans.a[1][2]=ans.a[2][1]=ans.a[3][3]=0; 105 } 106 return ans; 107 } 108 namespace Graph{ 109 int vis[M],f[M]; 110 queue<int>q; 111 set<int>S[N]; 112 map<int,int>mat[N]; 113 void add(int x,int y,int z); 114 void del(int x,int y){ 115 mat[x][y]=0,S[x].erase(y),S[y].erase(x); 116 } 117 void Multi(int x,int y,int z){ 118 int k=mat[x][y]; 119 del(x,y); 120 trans[k]=get(1,w[z]),trans[z]=get(1,w[k]); 121 w[++V]=mul(trans[k],w[k]); 122 op[V]=1,v[V][0]=k,v[V][1]=z; 123 add(x,y,V); 124 } 125 void One(int x,int y){ 126 int k=mat[x][y]; 127 del(x,y); 128 trans[f[x]]=get(2,w[k],w[f[y]]); 129 trans[k]=get(3,w[f[x]],w[f[y]]); 130 trans[f[y]]=get(4,w[f[x]],w[k]); 131 w[++V]=mul(trans[k],w[k]); 132 op[V]=2,v[V][0]=f[x],v[V][1]=k,v[V][2]=f[y]; 133 f[y]=V; 134 if (S[y].size()<=2)q.push(y); 135 } 136 void Two(int k,int x,int y){ 137 int xx=mat[k][x],yy=mat[k][y]; 138 del(k,x),del(k,y); 139 trans[xx]=get(5,w[f[k]],w[yy]); 140 trans[f[k]]=get(6,w[xx],w[yy]); 141 trans[yy]=get(7,w[xx],w[f[k]]); 142 w[++V]=mul(trans[f[k]],w[f[k]]); 143 op[V]=3,v[V][0]=xx,v[V][1]=f[k],v[V][2]=yy; 144 add(x,y,V); 145 } 146 void Rev(int x,int y){ 147 int k=mat[x][y]; 148 mat[x][y]=0,S[x].erase(y),S[y].erase(x); 149 trans[k]=get(8); 150 w[++V]=mul(trans[k],w[k]); 151 op[V]=4,v[V][0]=k; 152 add(y,x,V); 153 } 154 void add(int x,int y,int z){ 155 if (mat[y][x])Rev(y,x); 156 if (mat[x][y]){ 157 Multi(x,y,z); 158 return; 159 } 160 mat[x][y]=z,S[x].insert(y),S[y].insert(x); 161 if (S[x].size()<=2)q.push(x); 162 if (S[y].size()<=2)q.push(y); 163 } 164 void build(){ 165 while (!q.empty())q.pop(); 166 for(int i=1;i<=n;i++){ 167 f[i]=i; 168 if (S[i].size()<=2)q.push(i); 169 } 170 while (!q.empty()){ 171 int k=q.front(); 172 q.pop(); 173 if ((vis[k])||(!S[k].size()))continue; 174 vis[k]=1; 175 if (S[k].size()==1){ 176 int x=(*S[k].begin()); 177 if (mat[x][k])Rev(x,k); 178 One(k,x); 179 } 180 else{ 181 int x=(*S[k].begin()),y=(*++S[k].begin()); 182 if (mat[x][k])Rev(x,k); 183 if (mat[y][k])Rev(y,k); 184 Two(k,x,y); 185 } 186 } 187 } 188 }; 189 namespace Tree{ 190 int son[5]={0,2,3,3,1},fa[M],sz[M],mx[M],dfn[M],top[M],tail[M]; 191 matrix f[M<<2]; 192 void update(int k,int l,int r,int x,matrix y){ 193 if (l==r){ 194 f[k]=y; 195 return; 196 } 197 if (x<=mid)update(L,l,mid,x,y); 198 else update(R,mid+1,r,x,y); 199 f[k]=mul(f[L],f[R]); 200 } 201 matrix query(int k,int l,int r,int x,int y){ 202 if ((x<=l)&&(r<=y))return f[k]; 203 if (y<=mid)return query(L,l,mid,x,y); 204 if (x>mid)return query(R,mid+1,r,x,y); 205 return mul(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 206 } 207 void dfs1(int k,int f){ 208 fa[k]=f,sz[k]=1; 209 for(int i=0;i<son[op[k]];i++){ 210 dfs1(v[k][i],k); 211 sz[k]+=sz[v[k][i]]; 212 if (sz[v[k][i]]>sz[mx[k]])mx[k]=v[k][i]; 213 } 214 } 215 void dfs2(int k,int f,int t){ 216 dfn[k]=++dfn[0],top[k]=t; 217 if (f)update(1,1,V,dfn[k],trans[k]); 218 if (!mx[k])tail[k]=k; 219 else{ 220 dfs2(mx[k],k,t); 221 tail[k]=tail[mx[k]]; 222 } 223 for(int i=0;i<son[op[k]];i++) 224 if (v[k][i]!=mx[k])dfs2(v[k][i],k,v[k][i]); 225 } 226 void build(){ 227 dfs1(V,0); 228 dfs2(V,0,V); 229 } 230 void update(int k){ 231 while (1){ 232 k=top[k]; 233 if (k!=tail[k])w[k]=mul(query(1,1,V,dfn[k]+1,dfn[tail[k]]),w[tail[k]]); 234 if (k==V)return; 235 k=fa[k]; 236 if (op[k]==1)trans[mx[k]]=get(1,w[v[k][0]+v[k][1]-mx[k]]); 237 else{ 238 int p=(op[k]-2)*3; 239 if (mx[k]==v[k][0])trans[mx[k]]=get(2+p,w[v[k][1]],w[v[k][2]]); 240 if (mx[k]==v[k][1])trans[mx[k]]=get(3+p,w[v[k][0]],w[v[k][2]]); 241 if (mx[k]==v[k][2])trans[mx[k]]=get(4+p,w[v[k][0]],w[v[k][1]]); 242 } 243 update(1,1,V,dfn[mx[k]],trans[mx[k]]); 244 } 245 } 246 ll query(){ 247 return max(w[V].a[0][0],w[V].a[1][0]); 248 } 249 }; 250 int main(){ 251 n=read(),m=read(),V=n+m; 252 for(int i=1;i<=n;i++){ 253 w[i].n=2,w[i].m=1; 254 for(int j=0;j<2;j++)w[i].a[j][0]=read(); 255 } 256 for(int i=n+1;i<=n+m;i++){ 257 x=read(),y=read(); 258 w[i].n=4,w[i].m=1; 259 for(int j=0;j<2;j++)w[i].a[j][0]=w[i].a[3-j][0]=read(); 260 Graph::add(x,y,i); 261 } 262 Graph::build(); 263 Tree::build(); 264 write(Tree::query(),'\n'); 265 q=read(); 266 for(int i=1;i<=q;i++){ 267 x=read(); 268 for(int j=0;j<2;j++)w[x].a[j][0]=read(); 269 if (x>n){ 270 w[x].a[2][0]=w[x].a[1][0]; 271 w[x].a[3][0]=w[x].a[0][0]; 272 } 273 Tree::update(x); 274 write(Tree::query(),'\n'); 275 } 276 return 0; 277 }
下面,给出每种运算的构造以及每 一个参与运算的变量需要左乘的矩阵(依次给出),以供参考
$$
\left[\begin{matrix}a_{1}\\b_{1}\\c_{1}\\d_{1}\end{matrix}\right]\oplus \left[\begin{matrix}a_{2}\\b_{2}\\c_{2}\\d_{2}\end{matrix}\right]=\left[\begin{matrix}a_{1}+a_{2}\\b_{1}+b_{2}\\c_{1}+c_{2}\\d_{1}+d_{2}\end{matrix}\right]\\\left[\begin{matrix}a_{2}&-\infty&-\infty&-\infty\\-\infty&b_{2}&-\infty&-\infty\\-\infty&-\infty&c_{2}&-\infty\\-\infty&-\infty&-\infty&d_{2}\end{matrix}\right],\left[\begin{matrix}a_{1}&-\infty&-\infty&-\infty\\-\infty&b_{1}&-\infty&-\infty\\-\infty&-\infty&c_{1}&-\infty\\-\infty&-\infty&-\infty&d_{1}\end{matrix}\right]
$$
$$
\odot\left(\left[\begin{matrix}a_{1}\\b_{1}\end{matrix}\right],\left[\begin{matrix}a_{2}\\b_{2}\\c_{2}\\d_{2}\end{matrix}\right],\left[\begin{matrix}a_{3}\\b_{3}\end{matrix}\right]\right)=\left[\begin{matrix}\max(a_{1}+a_{2},b_{1}+c_{2})+a_{3}\\\max(a_{1}+b_{2},b_{1}+d_{2})+b_{3}\end{matrix}\right]\\\left[\begin{matrix}a_{2}+a_{3}&c_{2}+a_{3}\\b_{2}+b_{3}&d_{2}+b_{3}\end{matrix}\right],\left[\begin{matrix}a_{1}+a_{3}&-\infty&b_{1}+a_{3}&-\infty\\-\infty&a_{1}+b_{3}&-\infty&b_{1}+b_{3}\end{matrix}\right],\left[\begin{matrix}\max(a_{1}+a_{2},b_{1}+c_{2})&-\infty\\-\infty&\max(a_{1}+b_{2},b_{1}+d_{2})\end{matrix}\right]
$$
$$
\otimes\left(\left[\begin{matrix}a_{1}\\b_{1}\\c_{1}\\d_{1}\end{matrix}\right],\left[\begin{matrix}a_{2}\\b_{2}\end{matrix}\right], \left[\begin{matrix}a_{3}\\b_{3}\\c_{3}\\d_{3}\end{matrix}\right]\right)=\left[\begin{matrix}\max(a_{1}+a_{2}+a_{3},c_{1}+b_{2}+c_{3})\\\max(a_{1}+a_{2}+b_{3},c_{1}+b_{2}+d_{3})\\\max(b_{1}+a_{2}+a_{3},d_{1}+b_{2}+c_{3})\\\max(b_{1}+a_{2}+b_{3},d_{1}+b_{2}+d_{3})\end{matrix}\right]\\\left[\begin{matrix}a_{2}+a_{3}&-\infty&b_{2}+c_{3}&-\infty\\a_{2}+b_{3}&-\infty&b_{2}+d_{3}&-\infty\\-\infty&a_{2}+a_{3}&-\infty&b_{2}+c_{3}\\-\infty&a_{2}+b_{3}&-\infty&b_{2}+d_{3}\end{matrix}\right],\left[\begin{matrix}a_{1}+a_{3}&c_{1}+c_{3}\\a_{1}+b_{3}&c_{1}+d_{3}\\b_{1}+a_{3}&d_{1}+c_{3}\\b_{1}+b_{3}&d_{1}+d_{3}\end{matrix}\right],\left[\begin{matrix}a_{1}+a_{2}&-\infty&c_{1}+b_{2}&-\infty\\-\infty&a_{1}+a_{2}&-\infty&c_{1}+b_{2}\\b_{1}+a_{2}&-\infty&d_{1}+b_{2}&-\infty\\-\infty&b_{1}+a_{2}&-\infty&d_{1}+b_{2}\end{matrix}\right]
$$
$$
R\left(\left[\begin{matrix}a\\b\\c\\d\end{matrix}\right]\right)=\left[\begin{matrix}a\\c\\b\\d\end{matrix}\right]\\\left[\begin{matrix}0&-\infty&-\infty&-\infty\\-\infty&-\infty&0&-\infty\\-\infty&0&-\infty&-\infty\\-\infty&-\infty&-\infty&0\end{matrix}\right]
$$