题目大意:给定一些形如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; } } }
时间: 2024-10-07 15:49:40