首页 > 代码库 > BZOJ 2762 JLOI2011 不等式组 树状数组

BZOJ 2762 JLOI2011 不等式组 树状数组

题目大意:给定一些形如ax+b>c的不等式,支持插入和修改,以及询问当x=k时有多少不等式成立

将不等式变形 可以得到每个不等式成立时x的取值范围 在树状数组上统计即可

注意事项:

1.a可以等于0 此时若b>c x∈R 若b<=c x∈?

2.x的取值范围可能超过[-1000000,1000000]

3.由于有负数 所以区间修改时左右端点都要加上1000001 若加上1000000则死循环

4.小于不是小于等于 注意整除是的讨论 我的做法是x>y大于就是x>=floor(y)+1 x<y就是x<=ceil(y)-1 这里不要加EPS否则会死

5.很坑的一点是数据虽然说保证合法但是我们可以无视这句话了…… 有重复删除的不等式 需要记录


简直可怕

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
#define RANGE 1000000
using namespace std;
int n,tot;
pair<int,int> intervals[M];
bool v[M];
int c[RANGE<<1|0xffff];
inline void Update(int x,int y)
{
	for(;x<=(RANGE<<1|1);x+=x&-x)
		c[x]+=y;
}
inline int Get_Ans(int x)
{
	int re=0;
	for(;x;x-=x&-x)
		re+=c[x];
	return re;
}
pair<int,int> Get_Interval(int a,int b,int c)
{
	if(a==0)
	{
		if(b>c) return make_pair(-RANGE,RANGE);
		else return make_pair(1,0);
	}
	else if(a>0)
	{
		int temp=floor(double(c-b)/a+1);
		if(temp<-RANGE)
			return make_pair(-RANGE,RANGE);
		if(temp>RANGE)
			return make_pair(1,0);
		return make_pair(temp,RANGE);
	} 
	{
		int temp=ceil(double(c-b)/a-1);
		if(temp>RANGE)
			return make_pair(-RANGE,RANGE);
		if(temp<-RANGE)
			return make_pair(1,0);
		return make_pair(-RANGE,temp);
	}
}
inline void Update(pair<int,int> x,int y)
{
	Update(x.first+RANGE+1,y);
	Update(x.second+RANGE+2,-y);
}
int main()
{
	int i,a,b,c,x;
	char p[10];
	cin>>n;
	for(i=1;i<=n;i++)
	{
		scanf("%s",p);
		switch(p[0])
		{
			case 'A':
				scanf("%d%d%d",&a,&b,&c);
				intervals[++tot]=Get_Interval(a,b,c);
				Update(intervals[tot],1);
				break;
			case 'Q':
				scanf("%d",&x);
				printf("%d\n", Get_Ans(x+RANGE+1) );
				break;
			case 'D':
				scanf("%d",&x);
				if(v[x]) break;v[x]=1;
				Update(intervals[x],-1);
				break;
		}
	}
}



BZOJ 2762 JLOI2011 不等式组 树状数组