2213. K个串
★★★★ 输入文件:bzoj_4504.in
输出文件:bzoj_4504.out
简单对比
时间限制:20 s 内存限制:512 MB
【题目描述】
兔子们在玩k个串的游戏。首先,它们拿出了一个长度为n的数字序列,选出其中的一
个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)。
兔子们想知道,在这个数字序列所有连续的子串中,按照以上方式统计其所有数字之和,第
k大的和是多少。
【输入格式】
第一行,两个整数n和k,分别表示长度为n的数字序列和想要统计的第k大的和
接下里一行n个数a_i,表示这个数字序列
【输出格式】
一行一个整数,表示第k大的和
【样例输入】
7 5
3 -2 1 2 2 1 3 -2
【样例输出】
4
【提示】
1 <= n <= 100000, 1 <= k <= 200000, 0 <= |a_i| <= 10^9数据保证存在第 k 大的和
和HDU 5654 xiaoxin and his watermelon candy几乎一模一样。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int maxn=100010; 8 const int INF=23333333; 9 int hash[maxn],a[maxn],n,k; 10 int head[maxn],nxt[maxn],pre[maxn]; 11 int rt[maxn],pos[maxn<<6]; 12 int ch[maxn<<6][2],cnt; 13 long long lx[maxn<<6],tr[maxn<<6]; 14 void Push_up(int x){ 15 int l=ch[x][0],r=ch[x][1]; 16 tr[x]=tr[l]+tr[r]; 17 if(lx[l]>tr[l]+lx[r]){ 18 lx[x]=lx[l]; 19 pos[x]=pos[l]; 20 } 21 else{ 22 lx[x]=tr[l]+lx[r]; 23 pos[x]=pos[r]; 24 } 25 } 26 void Build(int &rt,int l,int r){ 27 rt=++cnt; 28 if(l==r){ 29 pos[rt]=l; 30 if(!pre[l]){ 31 tr[rt]=hash[a[l]]; 32 lx[rt]=hash[a[l]]; 33 } 34 return; 35 } 36 int mid=(l+r)>>1; 37 Build(ch[rt][0],l,mid); 38 Build(ch[rt][1],mid+1,r); 39 Push_up(rt); 40 } 41 42 void Update(int pr,int &rt,int l,int r,int g,int d){ 43 rt=++cnt; 44 tr[rt]=tr[pr]+d; 45 if(l==r){ 46 pos[rt]=g; 47 lx[rt]=tr[rt]; 48 return; 49 } 50 ch[rt][0]=ch[pr][0]; 51 ch[rt][1]=ch[pr][1]; 52 int mid=(l+r)>>1; 53 if(g<=mid)Update(ch[pr][0],ch[rt][0],l,mid,g,d); 54 else Update(ch[pr][1],ch[rt][1],mid+1,r,g,d); 55 Push_up(rt); 56 } 57 struct data{int x;long long y;}; 58 data Query(int t,int l,int r,int x,int y) 59 { 60 if(l==x && r==y) return (data){pos[t],lx[t]}; 61 int mid=(l+r)>>1; 62 if(y<=mid) return Query(ch[t][0],l,mid,x,y); 63 else if(x>mid){ 64 data tmp=Query(ch[t][1],mid+1,r,x,y); 65 return (data){tmp.x,tmp.y+tr[ch[t][0]]}; 66 } 67 else{ 68 data tmp1=Query(ch[t][0],l,mid,x,mid); 69 data tmp2=Query(ch[t][1],mid+1,r,mid+1,y); 70 if(tmp1.y>tmp2.y+tr[ch[t][0]]) return tmp1; 71 else return (data){tmp2.x,tmp2.y+tr[ch[t][0]]}; 72 } 73 } 74 75 struct node{int i,l,r,x; long long y;}; 76 bool operator<(const node& a1,const node& a2) 77 {return a1.y<a2.y;} 78 priority_queue<node> q; 79 80 int main(){ 81 freopen("bzoj_4504.in","r",stdin); 82 freopen("bzoj_4504.out","w",stdout); 83 scanf("%d%d",&n,&k); 84 for(int i=1;i<=n;i++) 85 scanf("%d",&a[i]); 86 for(int i=1;i<=n;i++) 87 hash[i]=a[i]; 88 sort(hash+1,hash+n+1); 89 for(int i=1;i<=n;i++) 90 a[i]=lower_bound(hash+1,hash+n+1,a[i])-hash; 91 for(int i=1;i<=n;i++){ 92 pre[i]=head[a[i]]; 93 nxt[head[a[i]]]=i; 94 head[a[i]]=i; 95 } 96 Build(rt[1],1,n); 97 for(int i=1;i<n;i++){ 98 Update(rt[i],rt[i+1],1,n,i+1,-hash[a[i]]); 99 if(nxt[i])Update(rt[i+1],rt[i+1],1,n,nxt[i],hash[a[i]]); 100 } 101 for(int i=1;i<=n;i++){ 102 data tmp=Query(rt[i],1,n,i,n); 103 q.push((node){i,i,n,tmp.x,tmp.y}); 104 } 105 long long ans; 106 for(int i=1;i<=k;i++){ 107 node t=q.top(); q.pop(); ans=t.y; 108 if(t.l!=t.x){ 109 data tmp=Query(rt[t.i],1,n,t.l,t.x-1); 110 q.push((node){t.i,t.l,t.x-1,tmp.x,tmp.y}); 111 } 112 if(t.r!=t.x){ 113 data tmp=Query(rt[t.i],1,n,t.x+1,t.r); 114 q.push((node){t.i,t.x+1,t.r,tmp.x,tmp.y}); 115 } 116 } 117 printf("%lld\n",ans); 118 return 0; 119 }
有时间一定要重打!!!