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

建一棵树,其以0为根,且$1\le i\le 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$为根的子树内,选择若干个两两不成祖先-后代关系的点,$\sum\Delta_{p_{i}}$之和的最大值(忽略$S$的限制),对于$f$显然可以树形dp计算,复杂度为$o(n)$

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

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

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

将两部分拆开,也即$\sum_{x\in H}g_{x}-\sum_{x\in H,x\ne 0}f_{x}=g_{0}+\sum_{x\in H,x\ne 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. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 200005
  4. 4 #define ll long long
  5. 5 #define L (k<<1)
  6. 6 #define R (L+1)
  7. 7 #define mid (l+r>>1)
  8. 8 struct Edge{
  9. 9 int nex,to;
  10. 10 }edge[N];
  11. 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. 12 ll sum,ans,a[N],b[N],g[N],dp[N],dep[N];
  13. 13 void add(int x,int y){
  14. 14 edge[E].nex=head[x];
  15. 15 edge[E].to=y;
  16. 16 head[x]=E++;
  17. 17 }
  18. 18 int lca(int x,int y){
  19. 19 if (sh[x]<sh[y])swap(x,y);
  20. 20 for(int i=20;i>=0;i--)
  21. 21 if (sh[fa[x][i]]>=sh[y])x=fa[x][i];
  22. 22 if (x==y)return x;
  23. 23 for(int i=20;i>=0;i--)
  24. 24 if (fa[x][i]!=fa[y][i]){
  25. 25 x=fa[x][i];
  26. 26 y=fa[y][i];
  27. 27 }
  28. 28 return fa[x][0];
  29. 29 }
  30. 30 ll dis(int x,int y){
  31. 31 return dep[x]+dep[y]-2*dep[lca(x,y)];
  32. 32 }
  33. 33 ll dis_dfn(int x,int y){
  34. 34 return dis(idfn[x],idfn[y]);
  35. 35 }
  36. 36 void dfs1(int k){
  37. 37 for(int i=head[k];i!=-1;i=edge[i].nex){
  38. 38 dfs1(edge[i].to);
  39. 39 g[k]+=dp[edge[i].to];
  40. 40 }
  41. 41 dp[k]=min(g[k],b[k]);
  42. 42 }
  43. 43 void dfs2(int k,int f,int s1,ll s2){
  44. 44 idfn[x]=k;
  45. 45 dfn[k]=x++;
  46. 46 sh[k]=s1;
  47. 47 dep[k]=s2;
  48. 48 fa[k][0]=f;
  49. 49 for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
  50. 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. 51 }
  52. 52 void update(int k,int l,int r,int x,int y){
  53. 53 f[k]+=y;
  54. 54 if (l==r)return;
  55. 55 if (x<=mid)update(L,l,mid,x,y);
  56. 56 else update(R,mid+1,r,x,y);
  57. 57 }
  58. 58 int query(int k,int l,int r,int x){
  59. 59 if (l==r)return f[k];
  60. 60 if (x<=mid)return query(L,l,mid,x);
  61. 61 return query(R,mid+1,r,x);
  62. 62 }
  63. 63 int query_pre(int k,int l,int r,int x){
  64. 64 if ((!f[k])||(l>x))return -1;
  65. 65 if (l==r)return l;
  66. 66 int ans=query_pre(R,mid+1,r,x);
  67. 67 if (ans>=0)return ans;
  68. 68 return query_pre(L,l,mid,x);
  69. 69 }
  70. 70 int query_nex(int k,int l,int r,int x){
  71. 71 if ((!f[k])||(r<x))return -1;
  72. 72 if (l==r)return l;
  73. 73 int ans=query_nex(L,l,mid,x);
  74. 74 if (ans>=0)return ans;
  75. 75 return query_nex(R,mid+1,r,x);
  76. 76 }
  77. 77 int query_pre(int x){
  78. 78 int ans=query_pre(1,0,n,x-1);
  79. 79 if (ans>=0)return ans;
  80. 80 return query_pre(1,0,n,n);
  81. 81 }
  82. 82 int query_nex(int x){
  83. 83 int ans=query_nex(1,0,n,x+1);
  84. 84 if (ans>=0)return ans;
  85. 85 return query_nex(1,0,n,0);
  86. 86 }
  87. 87 ll calc(int k){
  88. 88 int x=query_pre(k),y=query_nex(k);
  89. 89 return dis_dfn(x,k)+dis_dfn(y,k)-dis_dfn(x,y);
  90. 90 }
  91. 91 int main(){
  92. 92 scanf("%d%d",&n,&q);
  93. 93 for(int i=1;i<=n;i++)scanf("%d",&p[i]);
  94. 94 for(int i=1;i<=n;i++){
  95. 95 scanf("%lld",&a[i]);
  96. 96 a[i]+=a[i-1];
  97. 97 }
  98. 98 for(int i=1;i<=n;i++)scanf("%lld",&b[i]);
  99. 99 for(int i=n;i;i--){
  100. 100 while ((st[0])&&(p[st[st[0]]]<p[i]))st[0]--;
  101. 101 if (!st[0])b[i]-=a[n]-a[i-1];
  102. 102 else b[i]-=a[st[st[0]]-1]-a[i-1];
  103. 103 st[++st[0]]=i;
  104. 104 }
  105. 105 memset(head,-1,sizeof(head));
  106. 106 st[0]=0;
  107. 107 for(int i=1;i<=n;i++){
  108. 108 while ((st[0])&&(p[st[st[0]]]<p[i]))st[0]--;
  109. 109 add(st[st[0]],i);
  110. 110 st[++st[0]]=i;
  111. 111 }
  112. 112 dfs1(0);
  113. 113 dfs2(0,0,0,0);
  114. 114 sum=g[0]+a[n];
  115. 115 update(1,0,n,0,1);
  116. 116 for(int i=1;i<=q;i++){
  117. 117 scanf("%d",&x);
  118. 118 int y=dfn[fa[x][0]];
  119. 119 if (!vis[x]){
  120. 120 update(1,0,n,y,1);
  121. 121 if (query(1,0,n,y)==1)ans+=calc(y);
  122. 122 }
  123. 123 else{
  124. 124 update(1,0,n,y,-1);
  125. 125 if (!query(1,0,n,y))ans-=calc(y);
  126. 126 }
  127. 127 vis[x]^=1;
  128. 128 printf("%lld\n",sum+ans/2);
  129. 129 }
  130. 130 }

[cf1495F]Squares的更多相关文章

  1. [LeetCode] Word Squares 单词平方

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

  2. 卡通图像变形算法(Moving Least Squares)附源码

    本文介绍一种利用移动最小二乘法来实现图像变形的方法,该方法由用户指定图像中的控制点,并通过拖拽控制点来驱动图像变形.假设p为原图像中控制点的位置,q为拖拽后控制点的位置,我们利用移动最小二乘法来为原图 ...

  3. Leetcode: Word Squares && Summary: Another Important Implementation of Trie(Retrieve all the words with a given Prefix)

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

  4. [LintCode] Perfect Squares 完全平方数

    Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 1 ...

  5. HDU 1264 Counting Squares(线段树求面积的并)

    Counting Squares Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. RSS(Residual Sum of Squares)的自由度为什么是n-1呢

    [转载请注明出处]http://www.cnblogs.com/mashiqi 在回归问题中,偶尔我们会遇到求方差的估计的情况.举了例子,我们常常通过Gaussian分布${\cal N}(\mu , ...

  7. poj-3739. Special Squares(二维前缀和)

    题目链接: I. Special Squares There are some points and lines parellel to x-axis or y-axis on the plane. ...

  8. [CareerCup] 7.5 A Line Cut Two Squares in Half 平均分割两个正方形的直线

    7.5 Given two squares on a two-dimensional plane, find a line that would cut these two squares in ha ...

  9. POJ 2002 Squares

    二分.... Squares Time Limit: 3500MS Memory Limit: 65536K Total Submissions: 14530 Accepted: 5488 Descr ...

随机推荐

  1. dg create datafile auto failed 排除处理

    1.Environment:11.2.0.4 dg 2.Symptoms:告警描述:Wed Sep 22 14:29:15 2021Errors in file /data/app/oracle/di ...

  2. 题解 「BJOI2018 治疗之雨」

    题目传送门 题目大意 有一个初始为 \(p\) 的数,每次操作分为以下两个: 有 \(\frac{1}{m+1}\) 的概率$+1,但是中途 \(p\) 的最大值只能为 \(n\)$ 有 \(k\) ...

  3. java设计模式_单例模式

    懒汉式 非线程安全 特点:Lazy 初始化.非多线程安全.易实现 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程.因为没有加锁 synchronized,所以严格意义上它并不算单 ...

  4. CentOS 7安装docker环境

    一.环境准备 Docker支持以下的CentOS版本: 1.Docker运行在CentOS 7(64-bit)上要求系统为64位,系统内核版本为3.10以上 2.Docker运行在Centos 6.5 ...

  5. Dapr-简介及环境搭建

    一.Dapr是什么? Dapr 是一个可移植的.事件驱动的运行时,它使任何开发人员能够轻松构建出弹性的.无状态和有状态的应用程序,并可运行在云平台或边缘计算中,它同时也支持多种编程语言和开发框架. 在 ...

  6. jq问题

    <div id="box"> <p> <span>A</span> <span>B</span> </ ...

  7. SharkCTF2021 fastcalc题记

    web --> python脚本编写练习. 直接访问发现全是乱码: 看包发现Content-Type里面没有charset=utf-8. 于是用python访问一下,用.encoding='ut ...

  8. 【UE4 设计模式】装饰器模式 Decorator Pattern

    概述 描述 动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活.是一种对象结构型模式. 套路 抽象构件(Component) 具体构 ...

  9. 【UE4 调试】提升UE4源码版本Setup下载速度

    更改setup.bat部分参数

  10. 92.反转链表II

    题目 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right .请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 . ...