K Seq HihoCoder - 1046 || BZOJ4504 k个串
这题与超级钢琴类似,然而重复的不重复计算贡献。。
那么先求出数组nxt,nxt[i]表示第i个元素之后的第一个与其相等的元素的下标,不存在则nxt[i]=0
考虑取的区间左端点为1时的情况。
将读入序列a中相等元素都只保留最先出现的,其余变为0,然后求前缀和,得到数组b。
此时可以知道,设f(l,r)为取下标在[l,r]区间内数时的答案,那么f(1,r)=b[r]。
考虑取的区间左端点为2时的情况。如何维护b数组,使得新的b数组也满足f(2,r)=b[r]?
手模样例区间左端点为1和2时符合要求的b。
样例:
7 5
3 -2 1 2 2 1 3
l=1: 3 1 2 4 4 4 4
l=2: 0 -2 -1 1 1 1 4
可以发现,做的操作相当于将b数组内下标在[1,nxt[1]-1]区间内的数减了(原来的)b[1]。
进一步推出,左端点为l时的b数组变到左端点l+1的b数组,就相当于将下标在[l,nxt[l]-1]区间内的数减了(原来的)b[l]。
(当然如果nxt[i]=0,那么就是将[l,n]内减b[l])
因此,可以用可持久化线段树处理出左端点为每一个位置时的b数组。可持久化线段树如果要传标记的话常数会很大(复杂度应该是对的...大概吧?),所以可以标记永久化
(不知道为什么网上的标记永久化那么长?吓得我还以为自己写错了233333)
(我写标记永久化时候困难重重,最后发现标记含义的定义还是类比普通线段树最容易实现(就是除当前节点外,以当前节点为根的子树内所有点的对应值都应加上当前节点的加法tag),另外给标记和记录的值一个明确的定义对于写清楚代码非常重要)
这样子之后就可以用类似超级钢琴的做法去做了...才怪。难道你真的跟我一样想要去写可持久化的带区间修改的区间第k大这样子一看就不靠谱的东西?
可以发现每一次对给定某一个b数组的查询,每次的区间都是一样的,一定是第一次第1大,第二次第2大,...
当然就可以用超级钢琴的后一种做法去做了(优先队列维护一下哪个b数组,哪一段区间的最大值是多少,在哪里,当某一段区间最大值被取出后,把该区间除了最大值所在位置剩下的最多两段取最大值放回优先队列)。'
(似乎也可以考虑暴力将原来的最大值加一个-inf?这样子下一次查找找到的就是该区间的次大啦(我没试过))
错误记录:
1.不知道为什么想到去维护最小值了,怎么过的样例啊
2.82-83行i+1写成i
#include<cstdio>
#include<algorithm>
#include<queue>
#include<tr1/unordered_map>
#define inf 0x3f3f3f3f3f3f3f3f
#define mid ((l+r)>>1)
using namespace std;
using namespace tr1;
typedef long long LL;
typedef pair<LL,LL> P;
LL lc[],rc[],addv[],mem;
//addv[i]表示i区间加法tag
P maxn[];//一对值:区间(只考虑自身及其下节点的标记)的最大值及下标
LL L,R,x;
LL root[],nxt[],a[],b[];
tr1::unordered_map<LL,LL> ttt1;
void build(LL l,LL r,LL &num)
{
num=++mem;
if(l==r) {maxn[num]=P(b[l],l);return;}
build(l,mid,lc[num]);build(mid+,r,rc[num]);
maxn[num]=max(maxn[lc[num]],maxn[rc[num]]);
}
void addx(LL l,LL r,LL &num)
{
LL t=num;num=++mem;lc[num]=lc[t];rc[num]=rc[t];maxn[num]=maxn[t];addv[num]=addv[t];
if(L<=l&&r<=R)
{
addv[num]+=x;maxn[num].first+=x;
return;
}
if(L<=mid) addx(l,mid,lc[num]);
if(mid<R) addx(mid+,r,rc[num]);
maxn[num]=max(maxn[lc[num]],maxn[rc[num]]);
maxn[num].first+=addv[num];
}
P query(LL l,LL r,LL num)
{
if(L<=l&&r<=R) return maxn[num];
P ans=P(-inf,);
if(L<=mid) ans=max(ans,query(l,mid,lc[num]));
if(mid<R) ans=max(ans,query(mid+,r,rc[num]));
ans.first+=addv[num];
return ans;
}
struct Info
{
Info(LL a=,LL b=,LL c=,LL d=,LL e=)
:ans(a),l(b),r(c),st(d),pos(e)
{}
LL ans,l,r,st,pos;
//root[st]中,[l,r]内最大值是ans,在pos位置
friend bool operator<(const Info &a,const Info &b)
{
return a.ans<b.ans;
}
};
LL n,k;
priority_queue<Info> q;
int main()
{
LL i;P t;Info t2;
scanf("%lld%lld",&n,&k);
for(i=;i<=n;i++) scanf("%lld",&a[i]);
for(i=;i<=n;i++)
{
b[i]=b[i-];
if(ttt1.count(a[i])==)
b[i]+=a[i];
else
nxt[ttt1[a[i]]]=i;
ttt1[a[i]]=i;
}
build(,n,root[]);
L=,R=n,t=query(,n,root[]);
q.push(Info(t.first,,n,,t.second));
for(i=;i<n;i++)
{
root[i]=root[i-];
L=i,R=i,x=-query(,n,root[i]).first;
L=i,R=nxt[i]?nxt[i]-:n,addx(,n,root[i]);
L=i+/**/,R=n,t=query(,n,root[i]);
q.push(Info(t.first,i+,n,i,t.second));//
}
for(i=;i<k;i++)
{
t2=q.top();q.pop();
L=t2.l,R=t2.pos-;
if(L<=R)
{
t=query(,n,root[t2.st]);
q.push(Info(t.first,L,R,t2.st,t.second));
}
L=t2.pos+,R=t2.r;
if(L<=R)
{
t=query(,n,root[t2.st]);
q.push(Info(t.first,L,R,t2.st,t.second));
}
}
t2=q.top();
printf("%lld",t2.ans);
return ;
}
K Seq HihoCoder - 1046 || BZOJ4504 k个串的更多相关文章
- hihocoder#1046: K个串
[传送门] 这种区间内相同数字只能被统计一次/只有区间内数字都不相同才对答案有贡献的题都可以用扫描线扫右端点,表示当前区间右端点为$r$.然后当前线段树/树状数组维护区间左端点为$[1,r)$时对应的 ...
- HihoCoder - 1807:好的数字串 (KMP DP)
Sample Input 6 1212 Sample Output 298 给定一个数字字符串S,如果一个数字字符串(只包含0-9,可以有前导0)中出现且只出现1次S,我们就称这个字符串是好的. 例如 ...
- 机器学习理论与实战(十)K均值聚类和二分K均值聚类
接下来就要说下无监督机器学习方法,所谓无监督机器学习前面也说过,就是没有标签的情况,对样本数据进行聚类分析.关联性分析等.主要包括K均值聚类(K-means clustering)和关联分析,这两大类 ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- 在数组a中,a[i]+a[j]=a[k],求a[k]的最大值,a[k]max——猎八哥fly
在数组a中,a[i]+a[j]=a[k],求a[k]的最大值,a[k]max. 思路:将a中的数组两两相加,组成一个新的数组.并将新的数组和a数组进行sort排序.然后将a数组从大到小与新数组比较,如 ...
- [Swift]LeetCode347. 前K个高频元素 | Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements. Example 1: Input: nums = [ ...
- [Swift]LeetCode692. 前K个高频单词 | Top K Frequent Words
Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...
- [leetcode]340. Longest Substring with At Most K Distinct Characters至多包含K种字符的最长子串
Given a string, find the length of the longest substring T that contains at most k distinct characte ...
- 【POJ】2449.Remmarguts' Date(K短路 n log n + k log k + m算法,非A*,论文算法)
题解 (搬运一个原来博客的论文题) 抱着板题的心情去,结果有大坑 就是S == T的时候也一定要走,++K 我发现按照论文写得\(O(n \log n + m + k \ log k)\)算法没有玄学 ...
随机推荐
- bzoj5105 晨跑 数论lcm
“无体育,不清华”.”每天锻炼一小时,健康工作五十年,幸福生活一辈子”在清华,体育运动绝对是同学们生活中 不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不过由于种种原因,每天都早 ...
- tyvj1045 最大的算式
描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号.例 ...
- Mac 系统引导过程概述 & BootCamp 的秘密
http://bbs.feng.com/read-htm-tid-6890655.html
- 1.spring boot要求最低jdk1.8,平安默认1.6问题,-》安装JDK1.8 2.maven 3.3.3要求最低jdk1.7->安装jdk 1.8
1.spring boot要求最低jdk1.8,平安默认1.6问题,->安装JDK1.82.maven 3.3.3要求最低jdk1.7->安装jdk 1.8
- sdfs
<!DOCTYPE html><html><head><meta charset="GB18030"><title>In ...
- dubbo安装和使用
转载:http://blog.csdn.net/zjcjava/article/details/78766095 背景 Dubbo的开源人梁飞在内部的交流会上宣布重启dubbo的维护和更新,具体PPT ...
- flask应用的分页
Flask-SQLAlchemy支持分页 https://www.jianshu.com/p/5e03cd202728
- Python 获取新浪微博的热门话题 (API)
Code: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-06-27 @author: guaguastd @name: ...
- android几个高速打包命令
在MTK android4.4 上,有几条命令能够高速打包system uaserdata bootimage,可提高效率. snod:这个命令是能够高速打包system.是不会运行android各 ...
- windows安装Python模块:requests
个人在windows10安装python模块requests如下过程: 1.下载requests模块:首先打开powershell, cd到你要下载文件的位置(我的是d:\softwareinstal ...