当前位置: 代码迷 >> 综合 >> Codeforces - Let Them Slide
  详细解决方案

Codeforces - Let Them Slide

热度:80   发布时间:2024-01-30 16:53:33.0

题目链接:Codeforces - Let Them Slide


因为序列的长度之和小于1e6.所以我们只要对每一次操作是O(长度)那么就是ok的。

若:l*2<=w
那么有很多区间的位置都是全部能贡献的,所以左右端点区间暴力更新,中间的直接用最大值更新。
否则:
枚举总区间的每个位置。看能贡献的地方,然后区间max。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int sum[N],m,n,mx[N<<2],l,a[N];
void add(int l,int r,int x){sum[l]+=x,sum[r+1]-=x;}
#define mid (l+r>>1)
void build(int p,int l,int r){if(l==r){mx[p]=a[l]; return ;}build(p<<1,l,mid),build(p<<1|1,mid+1,r);mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
int ask(int p,int l,int r,int ql,int qr){if(l==ql&&r==qr)	return mx[p];if(qr<=mid)	return ask(p<<1,l,mid,ql,qr);else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);else return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
signed main(){cin>>m>>n;for(int i=1;i<=m;i++){scanf("%lld",&l);for(int j=1;j<=l;j++)	scanf("%lld",&a[j]);if(l*2<=n){int mx=0;for(int j=1;j<=l;j++)	mx=max(mx,a[j]),add(j,j,mx);	mx=0;for(int j=l;j>=1;j--)	mx=max(mx,a[j]),add(n-l+j,n-l+j,mx);if(l*2<n)	add(l+1,n-l,mx);}else{a[l+1]=0;	build(1,0,l+1);for(int j=1;j<=n;j++)	add(j,j,ask(1,0,l+1,max(0LL,j-n+l),min(j,l+1)));}}for(int i=1;i<=n;i++)	sum[i]+=sum[i-1],printf("%lld ",sum[i]);return 0;
}
  相关解决方案