传送门
题意:求一个串子串和(定义为该串内不重复的元素和)第k大
算法:可持久化线段树+动态开点
思路:手动样例计算以第1、2、3……n个元素为串首的多个子串和,以S[i][]记以第i个元素为首的子串和们,预处理出每一个元素下一次出现的位置pos[i],会发现对于 j ∈ [i, pos − 1],S[i][j] 的元素值就等于 S[i − 1][j] 的元素值减去 val[i − 1],其他下标的元素的值不变。
于是我们对每个元素建立线段树,维护以它为首的子串长度值。找第k大时先把每个位置的线段树的最大值放进一个堆里,每次取出一个最大值并将其原位置的值改为无穷小。(注意inf要开大)重复k-1次该过程即可。
在维护线段树中最大值时Add的标记mk是没有下传的,因为每次Up加上了mk,递归回到根的过程中总会加上这个标记,这种维护最值而不是区间和的情况可以考虑标记不下传。
#include
#include
#include
#include
#define f first
#define s second
using namespace std;
typedef long long LL;
const int sm = 1e5+10;
const int sn = 1e7;
const LL inf = 1e14+50;
template <typename T> T Max(T x,T y) { return x>y?x:y; }
template <typename T> void read(T &x) {
char ch=getchar();int f=1;x=0;
while(ch>'9'||ch<'0') { if(ch=='-') f=-1;ch=getchar(); }
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); x*=f;
}
priority_queueint > >que;
int n,k,tot,cnt;
int Ls[sn],Rs[sn];
LL S[sm],mx[sn],mk[sn],pos[sn];//pos[sn]
int A[sm],B[sm],T[sm],ex[sm],nxt[sm];
int Hash(int x) {
return lower_bound(B+1,B+cnt+1,x)-B;
}
void Up(int rt) {
mx[rt]=Max(mx[Ls[rt]],mx[Rs[rt]])+mk[rt];//mk[rt]
pos[rt]=(mx[Ls[rt]]>mx[Rs[rt]])?pos[Ls[rt]]:pos[Rs[rt]];
}
void Build(int &rt,int l,int r) {
rt=++tot;
if(l==r) {
mx[rt]=S[l],pos[rt]=l;return;
}
int m=(l+r)>>1;
Build(Ls[rt],l,m);
Build(Rs[rt],m+1,r);
Up(rt);
}
void Modify(int &rt,int l,int r,int p) {//不要掉&
int pt=rt;rt=++tot;
mx[rt]=mx[pt],pos[rt]=pos[pt],mk[rt]=mk[pt],Ls[rt]=Ls[pt],Rs[rt]=Rs[pt];
if(l==r) { mx[rt]=mk[rt]=-inf; return; }
int m=(l+r)>>1;
if(p<=m) Modify(Ls[rt],l,m,p);
else Modify(Rs[rt],m+1,r,p);
Up(rt);
}
void Add(int pre,int &rt,int l,int r,int a,int b,int val) {
rt=++tot,mx[rt]=mx[pre],mk[rt]=mk[pre];
pos[rt]=pos[pre],Ls[rt]=Ls[pre],Rs[rt]=Rs[pre];
if(a<=l&&r<=b) {
mk[rt]+=val,mx[rt]+=val; return ;
}
int m=(l+r)>>1;
if(a<=m) Add(Ls[pre],Ls[rt],l,m,a,b,val);
if(b> m) Add(Rs[pre],Rs[rt],m+1,r,a,b,val);
Up(rt);
}
int main() {
read(n),read(k);
for(int i=1;i<=n;++i) read(A[i]),B[i]=A[i],nxt[i]=n+1;
sort(B+1,B+n+1);
cnt=unique(B+1,B+n+1)-B;
for(int i=1,hsh;i<=n;++i) {
hsh=Hash(A[i]);
if(!ex[hsh]) S[i]=S[i-1]+A[i],ex[hsh]=i;
else nxt[ex[hsh]]=i,ex[hsh]=i,S[i]=S[i-1];
}
Build(T[1],1,n);
que.push(make_pair(mx[T[1]],T[1]));
for(int i=2;i<=n;++i) {
Add(T[i-1],T[i],1,n,i,nxt[i-1]-1,-1*A[i-1]);
Modify(T[i],1,n,i-1);
que.push(make_pair(mx[T[i]],T[i]));
}
for(int i=1,p;i1,n,pos[p]);
que.push(make_pair(mx[p],p));
}
printf("%lld\n",que.top().f);
return 0;
}