【线段树】省选模拟51nod 小朋友的笑话

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88787830

题目:

在这里插入图片描述


分析:

辣鸡51nod
前两题迅速切掉花了1h
先写了一个 O ( n n l o g n ) O(n\sqrt n logn) 的算法,T了,开始想->放弃:1h
再写了一个 O ( n log 2 n ) O(n\log^2 n) 的算法,又T了,开始想->放弃:2h
最后无奈又想了一个 O ( n l o g n ) O(n log n) 的算法,没调完GG

最后一看 O ( n l o g n ) O(n log n) 尼玛要跑400ms左右。。这 O ( n l o g 2 n ) O(nlog^2n) 肯定过不去了。。但这特么N才1e5啊。。。

是没开O2导致set复杂度退化了吗…

题解给的方法和我最后想的方法差不多。。只不过他是用的set,我是想用线段树的懒标记维护

很显然,每种笑话是独立的,因此只需要考虑某种笑话的影响区间即可

所以,每次拿到一个新的区间,先把他覆盖的范围全部改为1,再和它原来同种笑话的区间求交,交的部分全部改为0。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
typedef pair<int,int> pii;
typedef set<pii>::iterator sit;
set<pii>col[MAXN];
int n,m;
int sum[MAXN*4],tag[MAXN*4];
void pushdown(int x,int l,int r){
	int mid=(l+r)>>1;
	if(tag[x]){
		tag[x<<1]=tag[x<<1|1]=tag[x];
		if(tag[x]==2){
			sum[x<<1]=mid-l+1;
			sum[x<<1|1]=r-mid;
		}
		else
			sum[x<<1]=sum[x<<1|1]=0;
		tag[x]=0;
	}
}
void pushup(int x){
	sum[x]=sum[x<<1]+sum[x<<1|1];	
}
void change(int id,int l,int r,int pl,int pr,int val){
//	PF("[%d %d %d]\n",pl,pr,val);
	if(l!=r)
		pushdown(id,l,r);
	if(pl<=l&&pr>=r){
		tag[id]=val+1;
		if(val==0)
			sum[id]=0;
		else
			sum[id]=r-l+1;
		return ;
	}
	int mid=(l+r)>>1;
	if(pl<=mid)
		change(id<<1,l,mid,pl,pr,val);
	if(pr>mid)
		change(id<<1|1,mid+1,r,pl,pr,val);
	pushup(id);
}
void add(int l,int r,int id){
	pii x=make_pair(l,l);
	sit itx=col[id].lower_bound(x);
	sit lft=itx,rit=itx;
	int pl=l,pr=r;
	bool flag=0;
	change(1,1,n,l,r,1);
	for(sit it=itx;itx!=col[id].begin();){
		it--;
		if(it->second<l)
			break;
		lft=it;
		change(1,1,n,max(l,it->first),min(r,it->second),0);
		pl=min(pl,it->first);
		itx=it;
	}
	for(sit it=itx;it!=col[id].end()&&it->first<=r;){
		change(1,1,n,max(l,it->first),min(r,it->second),0);
		pr=max(pr,it->second);
		it++;
		rit=it;
//		col[id].erase(it++);
	}
	for(sit it=lft;it!=rit;)
		col[id].erase(it++);
	col[id].insert(make_pair(pl,pr));
}
int query(int id,int l,int r,int pl,int pr){
	if(l!=r)
		pushdown(id,l,r);
	if(pl<=l&&pr>=r)
		return sum[id];
	int mid=(l+r)>>1;
	int res=0;
	if(pl<=mid)
		res+=query(id<<1,l,mid,pl,pr);
	if(pr>mid)
		res+=query(id<<1|1,mid+1,r,pl,pr);
	pushup(id);
	return res;
}
int main(){
	SF("%d%d",&n,&m);
	int opt,x,num,k,l,r;
	for(int i=1;i<=m;i++){
		SF("%d",&opt);
		if(opt==1){
			SF("%d%d%d",&x,&num,&k);
			l=x-k,r=x+k;
			add(l,r,num);
		}
		else{
			SF("%d%d",&l,&r);
			PF("%d\n",query(1,1,n,l,r));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/88787830