洛谷 P5482 [JLOI2011]不等式组 题解

37 篇文章 0 订阅

题目

一道线段树题目水题

开一棵线段树,第 i i i 个位置维护当 x = i x=i x=i 时成立的不等式数量
对于每次添加不等式的操作,先算出对应不等式的解集,可证这个解集是一段连续的区间(可能无限长)。接着将解集中对应的位置,并保存这个区间,方便以后撤销操作

查询 x = k x=k x=k 时直接单点查询就可以了

注意:本题要注意不等号的变向,以及 a = 0 a=0 a=0 的情况

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn=100010;
const int Maxm=2000010;
struct node{
	int l,r;
}g[Maxn];
int sum[Maxm];
bool vis[Maxn];
int n,m,q,cnt;
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
inline int down(int x,int y)
{
	double tmp=(1.0*x)/(1.0*y);
	if(x%y && tmp<0)
	return ((int)tmp-1);
	return x/y;
}
inline int lowbit(int x)
{
	return x&(-x);
}
void modify(int x,int k)
{
	while(x<=n)
	sum[x]+=k,x+=lowbit(x);
}
int query(int x)
{
	int ret=0;
	while(x)
	ret+=sum[x],x-=lowbit(x);
	return ret;
}
void add(int a,int c)
{
	++cnt;
	if(a==0)
	{
		if(c<0)g[cnt]=node{1,n};
		else g[cnt]=node{0,0};
	}
	else if(a>0)
	{
		g[cnt]=node{down(c,a)+1+m,n};
		if(g[cnt].l<1)g[cnt].l=1;
		if(g[cnt].l>n)g[cnt]=node{0,0};
	}
	else
	{
		g[cnt]=node{1,down(c,a)+m};
		if(c%a==0)--g[cnt].r;
		if(g[cnt].r>n)g[cnt].r=n;
		if(g[cnt].r<1)g[cnt]=node{0,0};
	}
	if(!g[cnt].l && !g[cnt].r)return;
	modify(g[cnt].l,1);
	if(g[cnt].r<n)
	modify(g[cnt].r+1,-1);
}
int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	q=read();
	n=2000001,m=1000001;
	while(q--)
	{
		char s[10];
		scanf("%s",s);
		if(s[0]=='A')
		{
			int a=read(),b=read(),c=read();
			add(a,c-b),vis[cnt]=1;
		}
		else if(s[0]=='D')
		{
			int pos=read();
			if(!vis[pos])continue;
			vis[pos]=0;
			if(!g[pos].l && !g[pos].r)
			continue;
			modify(g[pos].l,-1);
			if(g[pos].r<n)
			modify(g[pos].r+1,1);
		}
		else
		{
			int k=read();
			printf("%d\n",query(k+m));
		}
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值