题目链接:传送门
题目思路:对于每一个笑话,用动态开点线段树来维护区间是否被覆盖(笑话是否已经被这些人听过),先假定范围内全部没听过(置1),然后再将该范围包含的被覆盖的区间置0;
(也可以用set存一下二元组表示线段左右端点,每次二分查询暴力合并)
代码:
#include<bits/stdc++.h> #pragma GCC optimize(2) using namespace std; typedef long long LL; typedef unsigned long long uLL; typedef pair<int,int> pii; typedef pair<LL,LL> pLL; typedef pair<double,double> pdd; const int N=1e6+5; const int M=2e5+5; const int inf=1e8+5; const LL mod=1e9+7; const double eps=1e-8; const long double pi=acos(-1.0L); #define ls (i<<1) #define rs (i<<1|1) #define fi first #define se second #define pb push_back #define eb emplace_back #define mk make_pair #define mem(a,b) memset(a,b,sizeof(a)) LL read() { LL x=0,t=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') t=-1; while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return x*t; } struct node { int l,r,v; }; node c[N<<3]; int cnt,rt[N],t[N<<2],lz[N<<2],n,m; void pushdown(int i,int l,int r) { int mid=l+r>>1; lz[ls]=lz[rs]=lz[i]; t[ls]=lz[i]*(mid-l+1); t[rs]=lz[i]*(r-mid); lz[i]=-1; } void update(int &now,int l,int r,int ll,int rr) { if(now==0) now=++cnt; if(c[now].v) return ; if(ll<=l&&r<=rr) return (void)(c[now].v=1); int mid=l+r>>1; if(mid>=ll) update(c[now].l,l,mid,ll,rr); if(mid<rr) update(c[now].r,mid+1,r,ll,rr); c[now].v=min(c[c[now].l].v,c[c[now].r].v); } int query(int i,int l,int r,int ll,int rr) { if(ll<=l&&r<=rr) return t[i]; if(lz[i]!=-1) pushdown(i,l,r); int mid=l+r>>1,t1=0,t2=0; if(mid>=ll) t1=query(ls,l,mid,ll,rr); if(mid<rr) t2=query(rs,mid+1,r,ll,rr); return t1+t2; } void change(int i,int l,int r,int ll,int rr,int x) { //printf("x = %d , l = %d , r = %d ",x,l,r); if(ll<=l&&r<=rr) return (void)(t[i]=x*(r-l+1),lz[i]=x); if(lz[i]!=-1) pushdown(i,l,r); int mid=l+r>>1; if(mid>=ll) change(ls,l,mid,ll,rr,x); if(mid<rr) change(rs,mid+1,r,ll,rr,x); t[i]=t[ls]+t[rs]; } void ask(int now,int l,int r,int ll,int rr) { if(now==0) return ; if(c[now].v) { change(1,1,n,max(ll,l),min(rr,r),0); return ; } if(ll<=l&&r<=rr&&c[now].v) { change(1,1,n,l,r,0);//printf("l = %d , r = %d ",l,r); return ; } int mid=l+r>>1; if(mid>=ll) ask(c[now].l,l,mid,ll,rr); if(mid<rr) ask(c[now].r,mid+1,r,ll,rr); } int main() { mem(lz,-1); n=read(),m=read(); while(m--) { int op=read(); if(op==1){ int l=read(),x=read(),k=read(); change(1,1,n,max(1,l-k),min(n,l+k),1); ask(rt[x],1,n,max(1,l-k),min(n,l+k)); update(rt[x],1,n,max(1,l-k),min(n,l+k)); //printf("x = %d, rt = %d ",x,rt[x]); } else{ int l=read(),r=read(); printf("%d ",query(1,1,n,l,r)); } } return 0; }