给一段序列,给你去掉所有数字的顺序,输出每去掉一个数,当前联通的子序列的最大值。

倒着来,每次插入一个数,然后求联通的最大值,线段树每个节点标记一下,区间的左右是否插入了数字,还有如果有数字从左边/右边开始连续子序列的值,还有这个节点的区间是否连续。

 #include <cstdio>

 #include <algorithm>

 using namespace std;

 typedef long long LL;

 const int maxn=;

 int n;

 int i;

 int a[maxn+];

 int b[maxn+];

 LL res[maxn+];

 struct node{
int l,r;
LL sum;
int lflag,rflag;
LL lval,rval;
bool f;
}tree[maxn*+]; void push_up(int id){
int llf=tree[id<<].lflag;
int lrf=tree[id<<].rflag;
int rlf=tree[(id<<)+].lflag;
int rrf=tree[(id<<)+].rflag;
if(lrf&&rlf){
tree[id].sum=max(max(tree[id<<].rval+tree[(id<<)+].lval,tree[id<<].sum),tree[(id<<)+].sum);
tree[id].lflag=llf;
tree[id].rflag=rrf;
if(llf){
if(tree[id<<].f)
tree[id].lval=tree[id<<].lval+tree[(id<<)+].lval;
else tree[id].lval=tree[id<<].lval;
} else {
tree[id].lval=;
}
if(rrf){
if(tree[(id<<)+].f){
tree[id].rval=tree[(id<<)].rval+tree[(id<<)+].rval;
}
else tree[id].rval=tree[(id<<)+].rval;
} else {
tree[id].rval=;
}
tree[id].f=tree[(id<<)].f&&tree[(id<<)+].f;
}else if(!lrf||!rlf){
if(tree[id<<].sum>tree[(id<<)+].sum){
tree[id].sum=tree[id<<].sum;
tree[id].lflag=llf;
tree[id].rflag=rrf;
if(!llf)
tree[id].lval=;
else tree[id].lval=tree[id<<].lval;
if(!rrf)
tree[id].rval=;
else
tree[id].rval=tree[(id<<)+].rval;
tree[id].f=;
} else if(tree[id<<].sum<tree[(id<<)+].sum){
tree[id].sum=tree[(id<<)+].sum;
tree[id].lflag=llf;
tree[id].rflag=rrf;
if(!llf)
tree[id].lval=;
else tree[id].lval=tree[id<<].lval;
if(!rrf)
tree[id].rval=;
else
tree[id].rval=tree[(id<<)+].rval;
tree[id].f=;
} else if(tree[id<<].sum==tree[(id<<)+].sum){
tree[id].sum=tree[id<<].sum;
tree[id].lflag=llf;
tree[id].rflag=rrf;
if(!llf)
tree[id].lval=;
else tree[id].lval=tree[id<<].lval;
if(!rrf)
tree[id].rval=;
else
tree[id].rval=tree[(id<<)+].rval;
tree[id].f=;
} }
} void build(int id,int l,int r){
if(l==r){
tree[id].l=tree[id].r=l;
tree[id].sum=;
tree[id].lflag=tree[id].rflag=;
tree[id].lval=tree[id].rval=;
tree[id].f=;
return ;
}
int mid=(l+r)>>;
build(id<<,l,mid);
build((id<<)+,mid+,r);
push_up(id);
} void update(int id,int l,int r,int x,int val){
if(l==r){
tree[id].sum+=(LL)val;
tree[id].lflag=tree[id].rflag=;
tree[id].lval=tree[id].rval=val;
tree[id].f=;
return ;
}
int mid=(l+r)>>;
if(x<=mid){
update(id<<,l,mid,x,val);
} else {
update((id<<)+,mid+,r,x,val);
}
push_up(id);
} int main()
{
scanf("%d",&n);
build(,,n);
for(i=;i<=n;i++){
scanf("%d",&a[i]);
}
for(i=;i<=n;i++){
scanf("%d",&b[i]);
}
for(i=n;i>=;i--){
update(,,n,b[i],a[b[i]]);
res[i]=tree[].sum;
}
for(int i=;i<=n+;i++){
printf("%I64d\n",res[i]);
}
return ;
}

codeforces772C的更多相关文章

随机推荐

  1. C语言实现wc基本功能

    GitHub地址:https://github.com/hhx007/wc 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数. 这个项目要求写一个命令行程序,模仿已有w ...

  2. fscanf和fgets用法

    首先要对fscanf和fgets这两个文件函数的概念有深入的了解,对于字符串输入而言这两个函数有一个典型的区别是: fscanf读到空格或者回车时会把空格或回车转化为/(字符串结束符)而fgets函数 ...

  3. BZOJ2726:任务安排(DP+斜率优化+二分)

    机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务 ...

  4. 「LOJ#10036」「一本通 2.1 练习 2」Seek the Name, Seek the Fame (Hash

    题目描述 原题来自:POJ 2752 给定若干字符串(这些字符串总长 ≤4×105 \le 4\times 10^5 ≤4×105),在每个字符串中求出所有既是前缀又是后缀的子串长度. 例如:abab ...

  5. Pycharm用鼠标滚轮控制字体大小的

    Pycharm用鼠标滚轮控制字体大小的   一.pycharm字体放大的设置 File —> setting —> Keymap —>在搜寻框中输入:increase —> I ...

  6. JAVA,MYSQL,ORACLE的数据类型对比

    MySQL Data Type Oracle Data Type Java BIGINT NUMBER(19, 0) java.lang.Long BIT RAW byte[] BLOB BLOB,  ...

  7. caffe 逐步调试

    caffe 逐步调试 https://www.zhihu.com/question/27982282

  8. Apress 出版社电子书

    http://www.apress.com/ 国外收费电子书网站,电子书权威,比国内的还便宜

  9. 动态调用dll遇到的问题

    问题:动态调用第三方提供的dll报错. Run-Time Check Failure #0 - The value of ESP was not properly saved across a fun ...

  10. NFS资料

      Linux NFS服务器的安装与配置 http://www.cnblogs.com/mchina/archive/2013/01/03/2840040.html Linux NFS服务器的安装与配 ...