题解 CF780G 【Andryusha and Nervous Barriers】

绝顶我为峰

2021-05-09 20:28:37

Solution

模拟赛考了这题,写了个树套树没调出来/px 这道题几乎没有什么思维难度,是一个三维数点的板子,每个板子可以接住正上方一个 $s_i\times(r_i-l_i+1)$ 的矩形内的球,可以用树套树维护。 但是内层再开一个线段树会炸空间(我们模拟赛限制 256MB),~~并且不好写,不好调~~,我们考虑换个方法。 注意到对于每个位置上所有球,一个板子能接到的一定是一个区间,所以可以用堆直接维护每个位置上球的高度,数量即可。 然后需要维护每个区间的最小高度用来剪枝,防止在无用区间浪费时间。 对于每个板子,我们直接在矩形内查询,统计答案,然后分别在板子两侧加入同样数量的球即可。 ```cpp #include<iostream> #include<cstdio> #include<queue> #include<algorithm> using namespace std; #define int long long const int mod=1000000007; struct board { int h,l,r,s; bool operator <(const board &other) const { return h>other.h; } }a[100001]; int maxn,w,n,sum,ans[100001<<2]; priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q[100001]; inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x; } inline int ls(int k) { return k<<1; } inline int rs(int k) { return k<<1|1; } inline void push_up(int k) { ans[k]=min(ans[ls(k)],ans[rs(k)]); } void build(int k,int l,int r) { if(l==r) { q[l].push(make_pair(maxn+1,1)); ans[k]=maxn+1; return; } int mid=(l+r)>>1; build(ls(k),l,mid); build(rs(k),mid+1,r); push_up(k); } void update(int node,int l,int r,int k,int p,int h) { if(l==r) { q[l].push(make_pair(h,p)); ans[k]=min(ans[k],h); return; } int mid=(l+r)>>1; if(node<=mid) update(node,l,mid,ls(k),p,h); else update(node,mid+1,r,rs(k),p,h); push_up(k); } int query(int nl,int nr,int l,int r,int k,int h,int s) { if(ans[k]>h+s) return 0; if(l==r) { int res=0; while(!q[l].empty()&&q[l].top().first<=h+s) { res=(res+q[l].top().second)%mod; q[l].pop(); } ans[k]=q[l].empty()? 1e10+7:q[l].top().first; return res; } int mid=(l+r)>>1,res=0; if(nl<=mid) res=(res+query(nl,nr,l,mid,ls(k),h,s))%mod; if(nr>mid) res=(res+query(nl,nr,mid+1,r,rs(k),h,s))%mod; push_up(k); return res; } signed main() { maxn=read(),w=read(),n=read(); for(register int i=1;i<=n;++i) a[i].h=read(),a[i].l=read(),a[i].r=read(),a[i].s=read(); sum=w; build(1,1,w); sort(a+1,a+n+1); for(register int i=1;i<=n;++i) { int tmp=query(a[i].l,a[i].r,1,w,1,a[i].h,a[i].s); sum=(sum+tmp)%mod; if(a[i].l==1) update(a[i].r+1,1,w,1,(tmp<<1)%mod,a[i].h); else if(a[i].r==w) update(a[i].l-1,1,w,1,(tmp<<1)%mod,a[i].h); else { update(a[i].l-1,1,w,1,tmp,a[i].h); update(a[i].r+1,1,w,1,tmp,a[i].h); } } printf("%lld\n",sum); return 0; } ```