一道线段树题目水题
开一棵线段树,第
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;
}