数据结构(主席树):COGS 2213. K个串

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 }

  有时间一定要重打!!!

 

posted @ 2016-04-11 22:45  TenderRun  阅读(280)  评论(0编辑  收藏  举报