【BZOJ4504&&Hihocoder1046】K个串(主席树,堆)

题意:一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次)询问第k大的和是多少

1 <= n <= 100000, 1 <= k <= 200000, 0 <= a[i]<= 10^9

思路:类似于超级钢琴的思路

对于每一个右端点建立一棵主席树维护左端点的最大值

对于a[i]它对[last[a[i]]+1,i]有a[i]的贡献

再维护一个堆维护全局最大值

删除的时候就找到最大值的位置赋值成最小值

C++ STL 不会用 好烦

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<ctime>
  6 #include<cmath>
  7 #include<algorithm>
  8 #include<iomanip>
  9 #include<vector>
 10 #include<map>
 11 #include<set>
 12 #include<bitset>
 13 #include<queue>
 14 #include<stack>
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned int uint;
 18 typedef unsigned long long ull;
 19 typedef pair<int,int> PII;
 20 typedef vector<int> VI;
 21 #define fi first
 22 #define se second
 23 #define MP make_pair
 24 #define N   21000000
 25 #define M   110000
 26 #define eps 1e-8
 27 #define pi  acos(-1)
 28 #define oo  1e18
 29 #define MOD 10007
 30 
 31 struct node
 32 {
 33     ll v;
 34     int id;
 35     node()
 36     {
 37     }
 38     node(ll V,int P)
 39     {
 40         v=V; id=P;
 41     }
 42     friend bool operator <(node x,node y)
 43     {
 44         return x.v<y.v;
 45     }
 46 };
 47 
 48 struct tree
 49 {
 50     int l,r;
 51     ll a,s;
 52 }t[N];
 53 
 54 priority_queue<node>q;
 55 map<int,int>last;
 56 int a[M],root[M],n,cnt;
 57 
 58 void pushup(int p)
 59 {
 60     t[p].s=0;
 61     if(!t[p].r) t[p].s=t[t[p].l].s;
 62      else if(!t[p].l) t[p].s=t[t[p].r].s;
 63       else t[p].s=max(t[t[p].l].s,t[t[p].r].s);
 64     t[p].s+=t[p].a;
 65 }
 66 
 67 void update(int l,int r,int x,int y,int v,int &r1,int r2)
 68 {
 69     r1=++cnt;
 70     t[r1]=t[r2];
 71     if(x<=l&&r<=y)
 72     {
 73         t[r1].a+=v;
 74         pushup(r1);
 75         return;
 76     }
 77     int mid=(l+r)>>1;
 78     if(x<=mid) update(l,mid,x,y,v,t[r1].l,t[r2].l);
 79     if(y>mid) update(mid+1,r,x,y,v,t[r1].r,t[r2].r);
 80     pushup(r1);
 81 }
 82 
 83 void del(int l,int r,int &p)
 84 {
 85     int x=p;
 86     p=++cnt;
 87     t[cnt]=t[x];
 88     if(l==r)
 89     {
 90         t[p].a=-oo;
 91         pushup(p);
 92         return;
 93     }
 94     int mid=(l+r)>>1;
 95     if(!t[p].r) del(l,mid,t[p].l);
 96      else if(!t[p].l) del(mid+1,r,t[p].r);
 97       else
 98       {
 99               if(t[t[p].l].s>=t[t[p].r].s) del(l,mid,t[p].l);
100                else del(mid+1,r,t[p].r);
101       }
102     pushup(p);
103 }
104     
105 
106 int main()
107 {
108     //freopen("bzoj4504.in","r",stdin);
109     //freopen("bzoj4504.out","w",stdout); 
110     int k;
111     scanf("%d%d",&n,&k);
112     cnt=0;
113     for(int i=1;i<=n;i++)
114     {
115         scanf("%d",&a[i]);
116         update(1,n,i,i,0,root[i],root[i-1]);
117         update(1,n,last[a[i]]+1,i,a[i],root[i],root[i]);
118         last[a[i]]=i;
119         q.push(node(t[root[i]].s,i));
120     }
121     for(int i=1;i<k;i++)
122     {
123         int x=q.top().id;
124         q.pop();
125         del(1,n,root[x]);
126         q.push(node(t[root[x]].s,x));
127     }
128     printf("%lld\n",q.top().v);
129     return 0;
130 }
131     
132     

 

posted on 2018-10-29 22:35  myx12345  阅读(176)  评论(0编辑  收藏  举报

导航