zoukankan      html  css  js  c++  java
  • BZOJ 2006: [NOI2010]超级钢琴 [ST表+堆 | 主席树]

    题意: 一个序列,求k个不相同的长度属于$[L,R]$的区间使得和最大

    前缀和,对于每个r找最小的a[l]
    然后我yy了一个可持久化线段树做法...也许会T
    实际上主席树就可以了,区间k小值
    然后看hzwer题解发现还有更有趣的做法,差一点就想到了

    ((l,r,x))表示左端点在([l,r]),右端点为(x)的最大和
    用优先队列维护
    取出((l,r,x))后,区间被分成两段,再加入就行了

    MD我连ST表都写错

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int N=5e5+5, INF=1e9;
    #define pii pair<int, int>
    #define MP make_pair 
    #define fir first
    #define sec second
    typedef long long ll;
    inline int read(){
    	char c=getchar();int x=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    
    int n, k, L, R, a[N], Log[N];
    struct meow{
    	int x, l, r; pii v;
    	bool operator <(const meow &a) const {return v < a.v;}
    	meow(){}
    	meow(int a, int b, int c, pii d):x(a), l(b), r(c), v(d){}
    };
    priority_queue<meow> q;
    pii f[N][21], t;
    void ini() {
    	for(int i=0; i<=n; i++) f[i][0] = MP(a[i], i);
    	for(int i=n; i>=0; i--)
    		for(int j=1; i + (1<<j) -1 <=n; j++)
    			f[i][j] = min(f[i][j-1], f[i+(1<<(j-1))][j-1]);// printf("f %d %d %d
    ",i,j,f[i][j].fir);
    }
    inline pii Min(int x, int y) { 
    	int t = Log[y-x+1]; //printf("
    Min %d %d  %d
    ",x,y, t);
    	return min(f[x][t], f[y - (1<<t) + 1][t]);
    }
    int main() {
    	freopen("in","r",stdin);
    	n=read(); k=read(); L=read(); R=read();
    	Log[1] = 0;
    	for(int i=2; i<=n; i++) Log[i] = Log[i>>1] + 1;
    	for(int i=1; i<=n; i++) a[i] = read()+a[i-1];
    	ini();
    	for(int i=L; i<=n; i++) {
    		int l = max(0, i-R), r = i-L;
    		t=Min(l, r); 
    		q.push(meow(i, l, r, MP(a[i] - t.fir, t.sec) ));
    	}
    
    	ll ans=0;
    	while(k--) {
    		meow now = q.top(); q.pop();
    		ans += now.v.fir;
    		int x = now.x, l = now.l, r = now.r, p = now.v.sec;
    		if(l < p) t=Min(l, p-1), q.push(meow(x, l, p-1, MP(a[x] - t.fir, t.sec) ));
    		if(p < r) t=Min(p+1, r), q.push(meow(x, p+1, r, MP(a[x] - t.fir, t.sec) ));
    	}
    	printf("%lld", ans);
    }
    
    
  • 相关阅读:
    02_5if switch分支与循环语句
    02_4运算符
    02_3程序格式
    Shell脚本调用ftp上传文件
    02_2数据类型转换
    02_1标识符_关键字_数据类型
    01_3Java Application初步
    01_2Java开发环境的下载 安装 配置
    Mac 安装MySQL
    用 Homebrew 带飞你的 Mac
  • 原文地址:https://www.cnblogs.com/candy99/p/6602765.html
Copyright © 2011-2022 走看看