zoukankan      html  css  js  c++  java
  • [cf1495F]Squares

    令$nex_{i}=min_{i<j,p_{i}<p_{j}}j$(即$i$的第2类边),若不存在此类$j$则$nex_{i}=n+1$

    建一棵树,其以0为根,且$1le ile n$的父亲为$max_{j<i,p_{i}<p_{j}}j$(不存在则为0),以下记作$fa_{i}$

    每一次选择$(i,nex_{i})$,都可以看作有一个收益$Delta_{i}=b_{i}-sum_{j=i}^{nex_{i}-1}a_{j}$

    问题也可以看作选择若干个节点$p_{1}<p_{2}<...<p_{k}$,使得$nex_{p_{i}}le p_{i+1}$且$(p_{i},nex_{p_{i}})$与$S$无公共点,在此条件下最小化$sum_{i=1}^{k}Delta_{p_{i}}+sum_{i=1}^{n}a_{i}$(后者为常数,以下忽略)

    考虑$(i,nex_{i})$,实际上这些点恰为以$i$为根的子树中的点(不包括$i$)

    (注意这棵树中,若$i$为$j$的祖先,则必然有$i<j$)

    由此,条件也即变为$p_{i}$之间两两不成祖先-后代关系,且$p_{i}$子树内(不包括$p_{i}$)不能含有$S$中的点

    (关于这两点性质,可以简单分类讨论地分析一下,具体这里就省略了)

    令$f_{i}$表示以$i$为根的子树内,选择若干个两两不成祖先-后代关系的点,$sumDelta_{p_{i}}$之和的最大值(忽略$S$的限制),对于$f$显然可以树形dp计算,复杂度为$o(n)$

    问题即求所有极浅的点,满足其子树内(不包括自己)没有$S$中的元素,这些点的$f$之和

    更具体的,令$H$为包含0以及$S$中所有元素的父亲的最小连通块,“满足其子树内(不包括自己)没有$S$中的元素”即等价于不在$H$中,因此问题即求$sum_{x otin H,fa_{x}in H}f_{x}$

    令$g_{x}=sum_{fa_{y}=x}f_{y}$,枚举$fa_{x}$并用$g_{x}$减去$xin H$的部分,即求$sum_{xin H}(g_{x}-sum_{fa_{y}=x,yin H}f_{y})$

    将两部分拆开,也即$sum_{xin H}g_{x}-sum_{xin H,x e 0}f_{x}=g_{0}+sum_{xin H,x e 0}g_{x}-f_{x}$(前者为常数,以下忽略)

    令$i$到$fa_{i}$的边权为$g_{i}-f_{i}$,也即求$H$中所有边权之和

    考虑将0以及$S$中所有元素的父亲按照dfs序排序,依次为$p_{1},p_{2},...,p_{k}$,答案即$frac{sum_{i=1}^{k}dis(p_{i},p_{i mod k+1})}{2}$

    (关于这个的正确性,这样从$p_{1}->p_{2}->...->p_{k}$,$H$中每一条边必然被经过恰好两次)

    关于这个,用线段树或set维护即可,复杂度为$o((n+q)log n)$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 200005
      4 #define ll long long
      5 #define L (k<<1)
      6 #define R (L+1)
      7 #define mid (l+r>>1)
      8 struct Edge{
      9     int nex,to;
     10 }edge[N];
     11 int E,n,q,x,p[N],head[N],st[N],dfn[N],idfn[N],sh[N],vis[N],fa[N][21],f[N<<2];
     12 ll sum,ans,a[N],b[N],g[N],dp[N],dep[N];
     13 void add(int x,int y){
     14     edge[E].nex=head[x];
     15     edge[E].to=y;
     16     head[x]=E++;
     17 }
     18 int lca(int x,int y){
     19     if (sh[x]<sh[y])swap(x,y);
     20     for(int i=20;i>=0;i--)
     21         if (sh[fa[x][i]]>=sh[y])x=fa[x][i];
     22     if (x==y)return x;
     23     for(int i=20;i>=0;i--)
     24         if (fa[x][i]!=fa[y][i]){
     25             x=fa[x][i];
     26             y=fa[y][i];
     27         }
     28     return fa[x][0];
     29 }
     30 ll dis(int x,int y){
     31     return dep[x]+dep[y]-2*dep[lca(x,y)];
     32 }
     33 ll dis_dfn(int x,int y){
     34     return dis(idfn[x],idfn[y]);
     35 }
     36 void dfs1(int k){
     37     for(int i=head[k];i!=-1;i=edge[i].nex){
     38         dfs1(edge[i].to);
     39         g[k]+=dp[edge[i].to];
     40     }
     41     dp[k]=min(g[k],b[k]);
     42 }
     43 void dfs2(int k,int f,int s1,ll s2){
     44     idfn[x]=k;
     45     dfn[k]=x++;
     46     sh[k]=s1;
     47     dep[k]=s2;
     48     fa[k][0]=f;
     49     for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
     50     for(int i=head[k];i!=-1;i=edge[i].nex)dfs2(edge[i].to,k,s1+1,s2+g[edge[i].to]-dp[edge[i].to]);
     51 }
     52 void update(int k,int l,int r,int x,int y){
     53     f[k]+=y;
     54     if (l==r)return;
     55     if (x<=mid)update(L,l,mid,x,y);
     56     else update(R,mid+1,r,x,y);
     57 }
     58 int query(int k,int l,int r,int x){
     59     if (l==r)return f[k];
     60     if (x<=mid)return query(L,l,mid,x);
     61     return query(R,mid+1,r,x);
     62 }
     63 int query_pre(int k,int l,int r,int x){
     64     if ((!f[k])||(l>x))return -1;
     65     if (l==r)return l;
     66     int ans=query_pre(R,mid+1,r,x);
     67     if (ans>=0)return ans;
     68     return query_pre(L,l,mid,x);
     69 }
     70 int query_nex(int k,int l,int r,int x){
     71     if ((!f[k])||(r<x))return -1;
     72     if (l==r)return l;
     73     int ans=query_nex(L,l,mid,x);
     74     if (ans>=0)return ans;
     75     return query_nex(R,mid+1,r,x);
     76 }
     77 int query_pre(int x){
     78     int ans=query_pre(1,0,n,x-1);
     79     if (ans>=0)return ans;
     80     return query_pre(1,0,n,n);
     81 }
     82 int query_nex(int x){
     83     int ans=query_nex(1,0,n,x+1);
     84     if (ans>=0)return ans;
     85     return query_nex(1,0,n,0);
     86 }
     87 ll calc(int k){
     88     int x=query_pre(k),y=query_nex(k);
     89     return dis_dfn(x,k)+dis_dfn(y,k)-dis_dfn(x,y);
     90 }
     91 int main(){
     92     scanf("%d%d",&n,&q);
     93     for(int i=1;i<=n;i++)scanf("%d",&p[i]);
     94     for(int i=1;i<=n;i++){
     95         scanf("%lld",&a[i]);
     96         a[i]+=a[i-1];
     97     }
     98     for(int i=1;i<=n;i++)scanf("%lld",&b[i]);
     99     for(int i=n;i;i--){
    100         while ((st[0])&&(p[st[st[0]]]<p[i]))st[0]--;
    101         if (!st[0])b[i]-=a[n]-a[i-1];
    102         else b[i]-=a[st[st[0]]-1]-a[i-1];
    103         st[++st[0]]=i;
    104     }
    105     memset(head,-1,sizeof(head));
    106     st[0]=0;
    107     for(int i=1;i<=n;i++){
    108         while ((st[0])&&(p[st[st[0]]]<p[i]))st[0]--;
    109         add(st[st[0]],i);
    110         st[++st[0]]=i;
    111     }
    112     dfs1(0);
    113     dfs2(0,0,0,0);
    114     sum=g[0]+a[n];
    115     update(1,0,n,0,1);
    116     for(int i=1;i<=q;i++){
    117         scanf("%d",&x);
    118         int y=dfn[fa[x][0]];
    119         if (!vis[x]){
    120             update(1,0,n,y,1);
    121             if (query(1,0,n,y)==1)ans+=calc(y);
    122         }
    123         else{
    124             update(1,0,n,y,-1);
    125             if (!query(1,0,n,y))ans-=calc(y);
    126         }
    127         vis[x]^=1;
    128         printf("%lld
    ",sum+ans/2);
    129     }
    130 }
    View Code
  • 相关阅读:
    【Asp.Net从零开始】:上传文件(FileUpload)
    JavaScript变量声明及赋值
    427 类型数据
    427 自适应量化
    428 x264_reference_update
    427 expand_border
    426 pixel赋值问题 mbcmp函数 宏定义
    427 mb中一些参数记录备忘
    427 参考帧管理
    427 参数原来还有很多没有理解 比较详细的解释
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14742400.html
Copyright © 2011-2022 走看看