题解:CF815D Karen and Cards
前言
有点困难题。
思路分析
考虑本质上是三维问题,考虑降维处理。
因为全部满足条件不好做,考虑正难则反,计算不合法的三元组个数。
首先对 排序,从大往小做扫描线,每次维护 时 的最大不合法值,那么对于每一个 ,不合法的三元组数量等于全局和。
最开始,对于每个限制 ,设线段树维护的序列为 ,相当于 ,因为只需要满足一个,所以在区间 取 即可。
每次扫到限制 时, 的部分合法,而 的部分需要满足 ,相当于两次区间取 。
为了区间取 写 seg_beat 肯定不值当,注意到我们维护的序列 是有单调性的,所以直接线段树二分 + 区间推平就行。
总体复杂度 。
代码实现
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,p,q,r,ans,now,minb[500005],minc[500005],d[500005];
struct node{
int a,b,c;
}h[500005];
int val_sum[1000005],val_min[1000005],tag[1000005],ls[1000005],rs[1000005],dcnt,rt;
void pushup(int x){
val_sum[x]=val_sum[ls[x]]+val_sum[rs[x]];
val_min[x]=min(val_min[ls[x]],val_min[rs[x]]);
}
void pushdown(int l,int r,int x){
if(!tag[x]) return;
int mid=(l+r)>>1;
tag[ls[x]]=tag[rs[x]]=val_min[ls[x]]=val_min[rs[x]]=tag[x];
val_sum[ls[x]]=(mid-l+1)*tag[x];
val_sum[rs[x]]=(r-mid)*tag[x];
tag[x]=0;
}
void build(int l,int r,int &x){
x=++dcnt;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,ls[x]);
build(mid+1,r,rs[x]);
pushup(x);
}
void modify(int l,int r,int ql,int qr,int k,int x){
if(ql<=l && r<=qr){
val_min[x]=tag[x]=k;
val_sum[x]=(r-l+1)*k;
return;
}
pushdown(l,r,x);
int mid=(l+r)>>1;
if(ql<=mid) modify(l,mid,ql,qr,k,ls[x]);
if(qr>=mid+1) modify(mid+1,r,ql,qr,k,rs[x]);
pushup(x);
}
int findl(int l,int r,int ql,int qr,int k,int x){
if(l==r){
if(val_min[x]>k) return -1;
else return l;
}
pushdown(l,r,x);
int mid=(l+r)>>1,ans=-1;
if(ql<=mid){
if(val_min[ls[x]]<=k) ans=findl(l,mid,ql,qr,k,ls[x]);
if(ans!=-1) return ans;
}
if(qr>=mid+1){
if(val_min[rs[x]]<=k) ans=findl(mid+1,r,ql,qr,k,rs[x]);
if(ans!=-1) return ans;
}
return ans;
}
void add(int l,int r,int k){
int p=findl(1,q,l,r,k,rt);
if(p!=-1) modify(1,q,p,r,k,rt);
}
void init(){
for(int i=1;i<=n;i++){
add(1,h[i].b,h[i].c);
}
}
bool cmp(node a,node b){
return a.a<b.a;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>p>>q>>r;
for(int i=1;i<=n;i++){
cin>>h[i].a>>h[i].b>>h[i].c;
}
sort(h+1,h+1+n,cmp);
build(1,q,rt);
init();
now=n;
for(int i=p;i>=1;i--){
while(now && h[now].a>=i){
add(h[now].b+1,q,h[now].c);
add(1,h[now].b,r);
now--;
}
ans+=val_sum[1];
}
cout<<p*q*r-ans;
return 0;
}
本文作者:Kenma
本文链接:https://www.cnblogs.com/Kenma/p/18689774
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步