bzoj : 4504: K个串 区间修改主席树
4504: K个串
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 268 Solved: 110
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
3 -2 1 2 2 1 3 -2
Sample Output
HINT
1 <= n <= 100000, 1 <= k <= 200000, 0 <= |a_i| <= 10^9数据保证存在第 k 大的和
看到这道题感觉一脸不可做,直到有人告我主席树是可以区间修改的,靠我以前一直以为不行的。。。
思路还是很简单的,和超级钢琴一样,用堆存一个五元组,表示一个右端点往左某个区间的局部最大值,每次分裂成两个,暴力找出前k大的就好了。
所以要用主席树维护一个区间min和支持区间打标记,这道题的标记可以永久化。
据yousiki说也可以支持push_down,只是查询的时候需要新建节点。
因为第一次写所以出现了很多神奇的错误。
最开始修改我是这么写的:
if(ll<=l&&rr>=r)
{
a[x].id=a[y].id;
a[x].lazy=a[y].lazy+z;
a[x].mn=a[x].lazy;
return ;
}
果断过不了样例,查着查着意识到好像区间修改和单点修改不太一样,x应该有左右儿子的!于是:
if(ll<=l&&rr>=r)
{
a[x].id=a[y].id;
a[x].lazy=a[y].lazy+z;
a[x].mn=a[x].lazy;
a[x].l=a[y].l;
a[x].r=a[y].r;
return ;
}
过样例后交上去wa,拍拍拍,拍出来后发现不对,x又不是叶子,它的min和lazy怎么可能相等!!!
if(lll<=l&&rr>=r)
{
a[x].id=a[y].id;
a[x].lazy=a[y].lazy+z;
a[x].mn=a[x].lazy+a[y].mn;
a[x].l=a[y].l;
a[x].r=a[y].r
return ;
}
小数据都拍过了,很高兴试了组大数据,不给面子的wa了,直觉告诉我还是这错了,我靠我在写什么,这顺序不对啊,我给x的mn加了两倍的y.lazy.
if(lll<=l&&rr>=r)
{
a[x].id=a[y].id;
a[x].lazy=a[y].lazy+z;
a[x].mn=z+a[y].mn;
a[x].l=a[y].l;
a[x].r=a[y].r
return ;
}
普天同庆,终于对了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 100005
#define ll long long
#define inf 1LL<<61
using namespace std;
int n,k;
struct node
{
int l,r,pos,rr;
ll zhi;
node(){;}
node(int _l,int _r,int _pos,int _rr,ll _zhi)
{
l=_l;r=_r;pos=_pos;rr=_rr;zhi=_zhi;
}
friend bool operator < (const node &aa,const node &bb)
{
return aa.zhi<bb.zhi;
}
};
priority_queue<node>q;
struct tree
{
int l,r,id;
ll lazy,mn;
tree()
{
lazy=mn=0;
}
}a[N*30]; int cnt;
int root[N];
int b[N];
vector<int>v[N];
void push_up(int x)
{
if(a[a[x].l].mn<a[a[x].r].mn)
{
a[x].mn=a[a[x].l].mn;
a[x].id=a[a[x].l].id;
}
else
{
a[x].mn=a[a[x].r].mn;
a[x].id=a[a[x].r].id;
}
a[x].mn+=a[x].lazy;
}
void build(int x,int l,int r)
{
a[x].id=l;
if(l==r)return ;
int mid=(l+r)>>1;
a[x].l=++cnt;a[x].r=++cnt;
build(a[x].l,l,mid);build(a[x].r,mid+1,r);
}
void insert(int x,int y,int l,int r,int lll,int rr,int z)
{
if(lll<=l&&rr>=r)
{
a[x].id=a[y].id;
a[x].lazy=a[y].lazy+z;
a[x].mn=z+a[y].mn;
a[x].l=a[y].l;
a[x].r=a[y].r;
return ;
}
a[x].lazy=a[y].lazy;
int mid=(l+r)>>1;
if(lll<=mid)
{
a[x].l=++cnt;
insert(a[x].l,a[y].l,l,mid,lll,rr,z);
}
else a[x].l=a[y].l;
if(rr>mid)
{
a[x].r=++cnt;
insert(a[x].r,a[y].r,mid+1,r,lll,rr,z);
}
else a[x].r=a[y].r;
push_up(x);
return ;
}
int ans1;ll ans2;
void qur(int x,int l,int r,int lll,int rr,ll now)
{
if(lll<=l&&rr>=r)
{
ll tmp=now+a[x].mn;
if(tmp<ans2)
{
ans1=a[x].id;ans2=tmp;
}
return ;
}
int mid=(l+r)>>1;
if(lll<=mid)qur(a[x].l,l,mid,lll,rr,now+a[x].lazy);
if(rr>mid)qur(a[x].r,mid+1,r,lll,rr,now+a[x].lazy);
return ;
}
ll sum[N];
int li[N],ct,nxt[N],now[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&b[i]),li[++ct]=b[i];
sort(li+1,li+ct+1);
ct=unique(li+1,li+ct+1)-li-1;
for(int i=1;i<=n;i++)b[i]=lower_bound(li+1,li+ct+1,b[i])-li;
for(int i=1;i<=ct;i++)now[i]=n+1;
for(int i=n;i>=1;i--)
{
nxt[i]=now[b[i]];
v[nxt[i]].push_back(i);
now[b[i]]=i;
}
memset(now,0,sizeof(now));
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1];
if(!now[b[i]])
{
now[b[i]]=1;
sum[i]+=li[b[i]];
}
}
cnt=0;
root[n+2]=++cnt;
build(1,0,n-1);
for(int i=n+1;i>=1;i--)
{
root[i]=root[i+1];
for(int j=0;j<v[i].size();j++)
{
if(v[i][j]==n)continue;
int tmp=root[i];root[i]=++cnt;
insert(root[i],tmp,0,n-1,v[i][j],n-1,li[b[v[i][j]]]);
}
}
for(int i=1;i<=n;i++)
{
ans2=inf;qur(root[i+1],0,n-1,0,i-1,0);
q.push(node(0,i-1,ans1,i,sum[i]-ans2));
}
for(int i=1;i<=k;i++)
{
node tmp=q.top();q.pop();
if(tmp.l!=tmp.pos)
{
ans2=inf;qur(root[tmp.rr+1],0,n-1,tmp.l,tmp.pos-1,0);
q.push(node(tmp.l,tmp.pos-1,ans1,tmp.rr,sum[tmp.rr]-ans2));
}
if(tmp.r!=tmp.pos)
{
ans2=inf;qur(root[tmp.rr+1],0,n-1,tmp.pos+1,tmp.r,0);
q.push(node(tmp.pos+1,tmp.r,ans1,tmp.rr,sum[tmp.rr]-ans2));
}
if(i==k)
{
printf("%lld\n",tmp.zhi);
}
}
return 0;
}
bzoj : 4504: K个串 区间修改主席树的更多相关文章
- bzoj 4504: K个串 可持久化线段树+堆
题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...
- BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序
Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路 ...
- BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树
题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...
- bzoj 4504: K个串【大根堆+主席树】
像超级钢琴一样把五元组放进大根堆,每次取一个出来拆开,(d,l,r,p,v)表示右端点为d,左端点区间为(l,r),最大区间和值为v左端点在p上 关于怎么快速求区间和,用可持久化线段树维护(主席树?) ...
- BZOJ 4504: K个串
题目大意: 求一个序列的第k大的子串和. 题解: 对于一个右端点找最优的左端点,扔进堆里. 每次取堆顶,将这个右端点可以选择的左端点的区间分成两段,扔进堆里,重复k次. 现在需要对于一个固定的右端点, ...
- 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小
少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...
- [bzoj P4504] K个串
[bzoj P4504] K个串 [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次 ...
- 【bzoj1901】dynamic ranking(带修改主席树/树套树)
题面地址(权限题) 不用权限题的地址 首先说说怎么搞带修改主席树? 回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth. 那么我们如何支持修改操作 ...
- [BZOJ3295] [Cqoi2011]动态逆序对(带修改主席树)
题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...
随机推荐
- docker usage
docker ps -a 查看物理机上面所有容器信息列表 docker exec -it $docker_id /bin/bash 进入容器以默认帐号 docker exec -it -u root ...
- 【Py大法系列--01】20多行代码生成你的微信聊天机器人
前言 近期Stack Overflow公布了一项调查显示,Python已经成了发展最快的主流编程语言,Python搭乘着数据科学和机器学习以及人工智能的浪潮,席卷了整个技术圈.越来越多的人想了解.想学 ...
- jQuery获取复选框选中的每一个值
$('input[name="serviceMode"]:checked').each(function(){ this.attr('value') });
- Daily Srum 10.22
今天大家的状态比较好,但是还是有很多问题没有解决.首先就是服务器这方面,部分同学还不怎么会用:其次就是看代码出现了困难,不能完整地阅读:还有就是我们的昨天的任务有点困难,部分同学不能按时按量的完成!于 ...
- [buaa-SE-2017]个人作业-期末总结
个人作业-期末总结 Part1: 阅读作业 在这一部分,首先我将说说我对这次阅读作业中每篇文章的理解,最后结合这次团队项目的经理谈谈自己对软件开发的看法. 1. No Silver Bullet 文章 ...
- [BUAA_SE_2017]结对项目-数独程序扩展
结对项目-数独程序扩展 Runnable on x64 Only sudoku17.txt 须放置在可执行文件同目录中,可移步以下链接进行下载 Core-Github项目地址 GUI-Github项目 ...
- 冲刺One之站立会议2
在确定了总体目标之后,我们先决定了实现的具体功能,包括一个登陆界面,一个聊天室的主界面和服务器端的内容.我们今天完成了一小部分内容,把每个内容的主体框架搭建了起来. 效果如下图所示: 燃尽图2
- Chapter 9 软件实现
软件实现包括代码设计.设计审查.代码编写.代码走查.代码编译和单元测试等活动.程序设计语言有很多,从机器语言到高级语言一直发展.软件编码需要遵循一些规范,JAVA代码有适当的空行,代码行及行内空格.分 ...
- Git初用心得
第一次使用git,因为之前操作系统的实验需要,在虚拟机中使用过lniux系统,所以对这种用指令输入而不是图形化的程序感觉不是很陌生.感觉git还是很人性化的,git gui就是图形界面,操作起来也不复 ...
- Restful风格wcf调用
文章:Restful风格wcf调用 作者相当于把wcf服务改造成rest风格. Restful风格wcf调用2——增删改查 这篇文章在第一篇的基础上,进行了优化. Restful风格wcf调用3——S ...