zoukankan      html  css  js  c++  java
  • [loj3076]公园

    为了方便,对题意做以下处理:

    1.称"西部主题"和"科幻主题"分别为黑色和白色

    2.删去题中"保证没有两条不同的道路连接同一对景点"的条件

    关于题中的条件,即保证图中总存在重边、一度点或二度点(或仅剩一个点)

    (具体证明参考2019年的论文,这里就省略了)

    考虑对这些特殊的结构进行处理,具体如下——

    对于节点$x$,将其点权$w_{x}$用一个$2 imes 1$的矩阵描述,分别为$x$染黑色和白色的美观度

    对于边$(x,y)$,将其边权$v_{(x,y)}$用一个$4 imes 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$(结果为点权),使得合并后新点点权为$odotleft(w_{x},v_{e},w_{y} ight)$

    关于二度点,假设该点为$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 imes b,b imes c$和$a imes c$的矩阵,并且有$C_{i,j}=max_{k=1}^{b}(a_{i,k}+b_{k,j})$,显然其与矩阵乘法一样满足结合律

    通过这个运算,那么在这之前的四种运算中,每次运算结果都可以看作其中任意一个参与运算的变量左$*$一个矩阵(这个矩阵由剩下的参与运算的变量确定)

    由此,在每个位置上记录需要左$*$的矩阵,根据$*$的结合律即可用线段树维护(注意每次要从链尾算起)

    总复杂度为$o(nlog^{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=''){
     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(),'
    ');
    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(),'
    ');
    275     }
    276     return 0;
    277 } 
    View Code

    下面,给出每种运算的构造以及每 一个参与运算的变量需要左乘的矩阵(依次给出),以供参考

    $$
    left[egin{matrix}a_{1}\b_{1}\c_{1}\d_{1}end{matrix} ight]oplus left[egin{matrix}a_{2}\b_{2}\c_{2}\d_{2}end{matrix} ight]=left[egin{matrix}a_{1}+a_{2}\b_{1}+b_{2}\c_{1}+c_{2}\d_{1}+d_{2}end{matrix} ight]\left[egin{matrix}a_{2}&-infty&-infty&-infty\-infty&b_{2}&-infty&-infty\-infty&-infty&c_{2}&-infty\-infty&-infty&-infty&d_{2}end{matrix} ight],left[egin{matrix}a_{1}&-infty&-infty&-infty\-infty&b_{1}&-infty&-infty\-infty&-infty&c_{1}&-infty\-infty&-infty&-infty&d_{1}end{matrix} ight]
    $$

    $$
    odotleft(left[egin{matrix}a_{1}\b_{1}end{matrix} ight],left[egin{matrix}a_{2}\b_{2}\c_{2}\d_{2}end{matrix} ight],left[egin{matrix}a_{3}\b_{3}end{matrix} ight] ight)=left[egin{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} ight]\left[egin{matrix}a_{2}+a_{3}&c_{2}+a_{3}\b_{2}+b_{3}&d_{2}+b_{3}end{matrix} ight],left[egin{matrix}a_{1}+a_{3}&-infty&b_{1}+a_{3}&-infty\-infty&a_{1}+b_{3}&-infty&b_{1}+b_{3}end{matrix} ight],left[egin{matrix}max(a_{1}+a_{2},b_{1}+c_{2})&-infty\-infty&max(a_{1}+b_{2},b_{1}+d_{2})end{matrix} ight]
    $$

    $$
    otimesleft(left[egin{matrix}a_{1}\b_{1}\c_{1}\d_{1}end{matrix} ight],left[egin{matrix}a_{2}\b_{2}end{matrix} ight], left[egin{matrix}a_{3}\b_{3}\c_{3}\d_{3}end{matrix} ight] ight)=left[egin{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} ight]\left[egin{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} ight],left[egin{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} ight],left[egin{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} ight]
    $$

    $$
    Rleft(left[egin{matrix}a\b\c\dend{matrix} ight] ight)=left[egin{matrix}a\c\b\dend{matrix} ight]\left[egin{matrix}0&-infty&-infty&-infty\-infty&-infty&0&-infty\-infty&0&-infty&-infty\-infty&-infty&-infty&0end{matrix} ight]
    $$

  • 相关阅读:
    [Matlab.Matrix] 作为判断条件
    [Matlab.GUI] 学习小结
    [Modelsim] 初识
    [Matlab] isnan
    [Matlab] round
    [VS2012] 无法查找或打开 PDB 文件
    [Matlab.GUI]初识
    表格特效代码全集中
    JAVASCRIPT基础
    第4天:调用样式表
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15200906.html
Copyright © 2011-2022 走看看