[JZOJ 4815]【NOIP2016提高A组五校联考4】ksum
2016-10-07 15:09
417 查看
Sample Input
样例输入1:
3 4
1 3 4
样例输入2:
3 3
10 2 7
Sample Output
样例输出1:
8 7 4 4
样例输出2:
19 12 10
The Solution
我们可以发现,如果当前最大的是[l,r]字段,那么易得[l,r+1]子段和[l-1,r]子段一定之前就已经取出。
而且最大的子段一定是[1,n],
我们先把[1,n]放入堆里,
我们把子段加进一个堆,
假设当前堆顶是[a,b],这次之后,
[a+1,b]和[a,b-1]才有可能成为下次取出的对象,
那么我就将[a+1,b]和[a,b-1]加进堆,这样重复 k 次即可。时
间复杂度O(n log)。
Code
#include <cstdio> #include <iostream> #define fo(i,a,b) for (int i=a;i<=b;i++) #define N 200005 using namespace std; typedef long long ll; int num=0,n,k; ll Pre ; struct node { int l,r;ll sum; }a ; void Up(int x) { for (;x>1 && a[x].sum > a[x >> 1].sum;x >>= 1) swap(a[x],a[x >> 1]); } void Down(int x) { while (2*x <= num && a[x].sum <= a[2*x].sum || (2*x+1 <= num) && a[x].sum <= a[2*x+1].sum) { int y = 2 * x; if (y+1 <= num && a[y+1].sum > a[y].sum) y++; swap(a[x],a[y]); x=y; } } void Insert(int l,int r,ll s) { a[++ num].l = l; a[num].r = r; a[num].sum = s; Up(num); } void Delete(int x) { if (a[num].sum < a[x].sum) { a[x].l = a[num].l; a[x].r = a[num].r; a[x].sum = a[num --].sum; Down(x); } else { a[x].l = a[num].l; a[x].r = a[num].r; a[x].sum = a[num --].sum; Up(x); } } int main() { freopen("ksum.in","r",stdin); freopen("ksum.out","w",stdout); scanf("%d%d",&n,&k); int sum,x; fo(i,1,n) scanf("%d",&x),Pre[i]+=Pre[i-1]+(ll)x; Insert(1,n,Pre ); while (k--) { printf("%lld ",a[1].sum); if (a[1].l+1 <= a[1].r && a[1].r == n) Insert(a[1].l+1,a[1].r,Pre[a[1].r]-Pre[a[1].l]); if (a[1].l <= a[1].r-1) Insert(a[1].l,a[1].r-1,Pre[a[1].r-1]-Pre[a[1].l-1]); Delete(1); } return 0; }
这里有另一种库里的堆调用
#include<cstdio> #include<queue> using namespace std; struct data{int l,r;}p; long long pre[100001]; inline int read() { int data=0; char ch=0; while(ch<'0' || ch>'9') ch=getchar(); while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); return data; } inline bool operator<(data a,data b) { return pre[a.r]-pre[a.l-1]<pre[b.r]-pre[b.l-1]; } priority_queue <data> que; int main() { freopen("ksum.in","r",stdin); freopen("ksum.out","w",stdout); int n=p.r=read(),k=read(); for(int i=p.l=1;i<=n;i++) pre[i]=pre[i-1]+read(); que.push(p); while(k--) { p=que.top(); que.pop(); printf("%lld ",pre[p.r]-pre[p.l-1]); if(p.r==n) { p.l++; que.push(p); p.l--; } p.r--; que.push(p); } return 0; }
相关文章推荐
- JZOJ 4815. 【NOIP2016提高A组五校联考4】ksum
- JZOJ 4815 【NOIP2016提高A组五校联考4】ksum
- 【JZOJ4815】【NOIP2016提高A组五校联考4】ksum
- 16.10.7 A:4815. 【NOIP2016提高A组五校联考4】ksum
- 【JZOJ4817】【NOIP2016提高A组五校联考4】square
- JZOJ 4812 【NOIP2016提高A组五校联考2】string
- 【JZOJ 4813】【NOIP2016提高组 五校联考2】running
- JZOJ4817. 【NOIP2016提高A组五校联考4】square 二维rmq
- 【JZOJ 4817】【NOIP2016提高组 五校联考4】square
- JZOJ 4816. 【NOIP2016提高A组五校联考4】label
- 【JZOJ4812】【NOIP2016提高A组五校联考2】string
- JZOJ 4807 【NOIP2016提高A组五校联考3】破解
- 【JZOJ 4816】【NOIP2016提高组 五校联考4】label
- JZOJ【4817】. 【NOIP2016提高A组五校联考4】square
- 【JZOJ 4810】【NOIP2016提高组 五校联考1】道路规划
- JZOJ 4814. 【NOIP2016提高A组五校联考2】tree
- JZOJ 4816 【NOIP2016提高A组五校联考4】label
- JZOJ 4817. 【NOIP2016提高A组五校联考4】square
- 【JZOJ 4811】【NOIP2016提高组 五校联考1】排队
- JZOJ4813. 【NOIP2016提高A组五校联考2】