cf1208E Let Them Slide

链接

cf

思路

考虑点可以取到的区间,对于区间不满的暴力修改。
满的区间一起修改。因为不满的区间规模是数组长度的。
所以复杂度是 n l o g n nlogn nlogn的。
单调队列,st表,线段树都可以维护数组的区间最值。
最后答案差分输出。

代码

#include 
#define ll long long
using namespace std;
const int _=1e6+7,oo=0x3f3f3f3f;
int read() {
	int x=0,f=1;char s=getchar();
	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
	return x*f;
}
int T,n,w,q[_],st[_][21];
ll sum[_];
void init(int n) {
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)<=n+1;i++)
            st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int QQQ(int ql, int qr) {
    int k=(log2(qr-ql+1));
    return max(st[ql][k],st[qr-(1<<k)+1][k]);
}
int QQ(int ql,int qr) {
	if(max(ql,1)!=ql||min(qr,n)!=qr) 
		return max(0,QQQ(max(ql,1),min(qr,n)));
	else return QQQ(ql,qr);
}
int main() {
	T=read(),w=read();
	while(T --> 0) {
		n=read();
		for(int i=1;i<=n;++i) st[i][0]=read();
		init(n);
		for(int i=1;i<=n;++i) {
			int k=QQ(i,i+w-n);
			sum[i+w-n]+=k,sum[i+w-n+1]-=k;
		}
		for(int i=1;i<=min(w-n,n);++i) {
			int k=QQ(i-w+n,i);
			sum[i]+=k,sum[i+1]-=k;
		}
		if(n<w-n)  {			
			sum[n+1]+=max(0,QQ(1,n));
			sum[w-n+1]-=max(0,QQ(1,n));
		}
	}
	for(int i=1;i<=w;++i) sum[i]+=sum[i-1],printf("%I64d ",sum[i]);
	return 0;
}

你可能感兴趣的:(数据结构)