蒟蒻有一个小小的疑惑
查看原帖
蒟蒻有一个小小的疑惑
117395
Bob_Wang楼主2021/7/19 18:48

这个是错误代码

#include<cstdio>
#define maxn 100005
#define lid (k<<1)
#define rid (k<<1|1)
using namespace std;

struct node
{
	int l,r;
	int cnt0,cnt1;//记录0和1的数量
	int fl;//lazy标记
}tr[maxn*4];
int n,m,q;
int a[maxn],lq[maxn],rq[maxn],op[maxn];

void update(int k)
{
	tr[k].cnt0=tr[lid].cnt0+tr[rid].cnt0;
	tr[k].cnt1=tr[lid].cnt1+tr[rid].cnt1;
}

void pushdown(int k)
{
	int l=tr[k].l,r=tr[k].r;
	int mid=(l+r)>>1;
	if(tr[k].fl==0)
	{
		tr[lid].cnt0=mid-l+1;
		tr[lid].cnt1=0;
		tr[rid].cnt0=r-mid;
		tr[rid].cnt1=0;
		tr[lid].fl=tr[rid].fl=0;
	}
	else
	{
		tr[lid].cnt0=0;
		tr[lid].cnt1=mid-l+1;
		tr[rid].cnt0=0;
		tr[rid].cnt1=r-mid;
		tr[lid].fl=tr[rid].fl=1;
	}
	tr[k].fl=-1;
}

void build(int k,int l,int r,int val)
{
	tr[k].l=l;
	tr[k].r=r;
	tr[k].fl=-1;
	if(l==r)
	{
		tr[k].cnt0=tr[k].cnt1=0;
		if(a[l]>=val)tr[k].cnt1=1;
		else tr[k].cnt0=1;
		
	//	printf("%d ",tr[k].cnt1);
		
		return;
	}
	int mid=(l+r)>>1;
	build(lid,l,mid,val);
	build(rid,mid+1,r,val);
	update(k);
}//将大于mid的值赋为1,小于mid的值赋为0

void modify(int k,int l,int r,int c0,int c1,int opt)
{
	if(tr[k].l>=l&&tr[k].r<=r)
	{
		if(!opt)
		{
			if(tr[k].r<=l+c0-1)
			{
				tr[k].cnt0=tr[k].r-tr[k].l+1;
				tr[k].cnt1=0;
				tr[k].fl=0;
			}
			else if(tr[k].l>=l+c0)
			{
				tr[k].cnt0=0;
				tr[k].cnt1=tr[k].r-tr[k].l+1;
				tr[k].fl=1;
			}
			else
			{
				modify(lid,l,r,c0,c1,opt);
				modify(rid,l,r,c0,c1,opt);
				update(k);
			}
		}//从小到大
		else
		{
			if(tr[k].r<=l+c1-1)
			{
				tr[k].cnt1=tr[k].r-tr[k].l+1;
				tr[k].cnt0=0;
				tr[k].fl=1;
			}
			else if(tr[k].l>=l+c1)
			{
				tr[k].cnt1=0;
				tr[k].cnt0=tr[k].r-tr[k].l+1;
				tr[k].fl=0;
			}
			else
			{
				modify(lid,l,r,c0,c1,opt);
				modify(rid,l,r,c0,c1,opt);
				update(k);
			}
		}//从大到小
		return;
	}
	int mid=(tr[k].l+tr[k].r)>>1;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(l<=mid)
	modify(lid,l,r,c0,c1,opt);
	if(r>mid)
	modify(rid,l,r,c0,c1,opt);
	update(k);
}//区间修改

int query(int k,int l,int r,int opt)
{
	if(tr[k].l>=l&&tr[k].r<=r)
	return (opt==0)?tr[k].cnt0:tr[k].cnt1;
	int mid=(tr[k].l+tr[k].r)>>1;
	int ret=0;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(l<=mid)
	ret+=query(lid,l,r,opt);
	if(r>mid)
	ret+=query(rid,l,r,opt);
	return ret;
}//查询0/1个数

int query_p(int k,int pos)
{
	if(tr[k].l==tr[k].r)
	return tr[k].cnt1;
	int mid=(tr[k].l+tr[k].r)>>1;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(pos<=mid)
	return query_p(lid,pos);
	else return query_p(rid,pos);
}//单点查询

int check(int r)
{
	build(1,1,n,r);//建树
	
//	printf("\n");
	
	for(int i=1;i<=m;++i)
	{
		int cnt0,cnt1;
		cnt0=query(1,lq[i],rq[i],0);//查询0的数量
		cnt1=query(1,lq[i],rq[i],1);//查询1的数量
		modify(1,lq[i],rq[i],cnt0,cnt1,op[i]);
	}
	if(query_p(1,q))return 1;
	else return 0;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	scanf("%d",&a[i]);
	for(int i=1;i<=m;++i)
	scanf("%d%d%d",&op[i],&lq[i],&rq[i]);
	scanf("%d",&q);
	int l=1,r=n;
	while(l<r)
	{
		int mid=(l+r)>>1;
		
		//printf("mid=%d ",mid);
		
		if(check(mid))l=mid+1;
		else r=mid;
	}
	printf("%d",l-1);
	return 0;
}

这个是正确代码

#include<cstdio>
#define maxn 100005
#define lid (k<<1)
#define rid (k<<1|1)
using namespace std;

struct node
{
	int l,r;
	int cnt0,cnt1;//记录0和1的数量
	int fl;//lazy标记
}tr[maxn*4];
int n,m,q;
int a[maxn],lq[maxn],rq[maxn],op[maxn];

void update(int k)
{
	tr[k].cnt0=tr[lid].cnt0+tr[rid].cnt0;
	tr[k].cnt1=tr[lid].cnt1+tr[rid].cnt1;
}

void pushdown(int k)
{
	int l=tr[k].l,r=tr[k].r;
	int mid=(l+r)>>1;
	if(tr[k].fl==0)
	{
		tr[lid].cnt0=mid-l+1;
		tr[lid].cnt1=0;
		tr[rid].cnt0=r-mid;
		tr[rid].cnt1=0;
		tr[lid].fl=tr[rid].fl=0;
	}
	else
	{
		tr[lid].cnt0=0;
		tr[lid].cnt1=mid-l+1;
		tr[rid].cnt0=0;
		tr[rid].cnt1=r-mid;
		tr[lid].fl=tr[rid].fl=1;
	}
	tr[k].fl=-1;
}

void build(int k,int l,int r,int val)
{
	tr[k].l=l;
	tr[k].r=r;
	tr[k].fl=-1;
	tr[k].cnt0=tr[k].cnt1=0;
	if(l==r)
	{
		if(a[l]>=val)tr[k].cnt1=1;
		else tr[k].cnt0=1;
		return;
	}
	int mid=(l+r)>>1;
	build(lid,l,mid,val);
	build(rid,mid+1,r,val);
	update(k);
}//将大于mid的值赋为1,小于mid的值赋为0

void modify(int k,int l,int r,int opt)
{
	if(tr[k].l>=l&&tr[k].r<=r)
	{
		if(opt)
		{
			tr[k].cnt1=tr[k].r-tr[k].l+1;
			tr[k].cnt0=0;
			tr[k].fl=1;
		}
		else
		{
			tr[k].cnt0=tr[k].r-tr[k].l+1;
			tr[k].cnt1=0;
			tr[k].fl=0;
		}
		return;
	}
	int mid=(tr[k].l+tr[k].r)>>1;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(l<=mid)
	modify(lid,l,r,opt);
	if(r>mid)
	modify(rid,l,r,opt);
	update(k);
}//区间修改

int query(int k,int l,int r,int opt)
{
	if(tr[k].l>=l&&tr[k].r<=r)
	return (opt==0)?tr[k].cnt0:tr[k].cnt1;
	int mid=(tr[k].l+tr[k].r)>>1;
	int ret=0;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(l<=mid)
	ret+=query(lid,l,r,opt);
	if(r>mid)
	ret+=query(rid,l,r,opt);
	return ret;
}//查询0/1个数

int query_p(int k,int pos)
{
	if(tr[k].l==tr[k].r)
	return tr[k].cnt1;
	int mid=(tr[k].l+tr[k].r)>>1;
	if(tr[k].fl!=-1)
	pushdown(k);
	if(pos<=mid)
	return query_p(lid,pos);
	else return query_p(rid,pos);
}//单点查询

int check(int r)
{
	build(1,1,n,r);//建树
	for(int i=1;i<=m;++i)
	{
		int cnt0,cnt1;
		cnt0=query(1,lq[i],rq[i],0);//查询0的数量
		cnt1=query(1,lq[i],rq[i],1);//查询1的数量
		if(op[i])
		{
			modify(1,lq[i],lq[i]+cnt1-1,1);
			modify(1,rq[i]-cnt0+1,rq[i],0);
		}
		else
		{
			modify(1,lq[i],lq[i]+cnt0-1,0);
			modify(1,rq[i]-cnt1+1,rq[i],1);
		}
	}
	return query_p(1,q);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	scanf("%d",&a[i]);
	for(int i=1;i<=m;++i)
	scanf("%d%d%d",&op[i],&lq[i],&rq[i]);
	scanf("%d",&q);
	int l=1,r=n;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid))l=mid+1;
		else r=mid;
	}
	printf("%d",l-1);
	return 0;
}

它们只有check函数和modify函数不一样,但我觉得这两个程序是相同的,各位大佬能帮忙看一下问题出在哪里吗?

2021/7/19 18:48
加载中...