分类讨论大丈夫!!!WTF!!!
题意:
1.给你不等式ax>b
2.删除第i条插入的不等式
3.询问x=k时,满足多少个给定的不等式。
n的范围10w,k的绝对值范围是100w。
那么我们可以先解出这个不等式,把符合这个不等式的所有数所在的位置加一。
比如解出来x>1,就把2~100w全都加一。x<1,就把-100w~0全都加一。
那么明显就是修改区间,单点询问。可以用线段树很好的完成。
但是不知道为什么看到100w就后怕写线段树要玩常数。于是选择了树状数组。
用树状数组的话就需要差分。比如[l,r]都加一,那么在l的位置上加一,r+1的位置上减一。这个很基础。
负数的话下标怎么办呢?设置一个偏移量d=100w+1。修改第x个时,在第x+d个位置上修改。保证下标都是正的方便操作。
看来这道题已经没什么问题了。那我们去写写看?好的。
【以下为吐槽,看tips请跳过若干个自然段】
【四天前】树状数组两行秒。ax>b自以为是的除一除就算解好了。样例很快就过了。很自信的交上去。RE还是WA来着。。然后手忙脚乱改一改还是WA。。这个时候想到了对拍。网上搞了个标程拍一拍。。不拍不知道一拍吓一跳。。然后我就被拍扁重建了。(这是替罪羊树?
发现我解ax>b的方法很不科学。感觉都没考虑全。后来直接去玩double。结果精度萎出翔。。
然后我cave in了。。
【今天】上课的时候我重新想了想ax>b该怎么解。考虑a、b的正负,发现四种情况都列出来。四个if即可。最前面再特判一下a=0就没问题了。回来信心满满的写。
造了组大数据对拍过了。很高心。结果还是WA。真是要吐血。后来突然想到,万一它要删除已经删除掉的呢。那我不就挂了吗。于是我再开了个数组记录。这回,过了。。。。。
【吐槽完了】
几个tips:
1.a=0要特判
2.ax>b分四种情况讨论(我是这么做的保险,或者有更神的方法,可惜我不会
3.如果x解出来不在-100w~100w之间要特判
4.删除已经删除的不等式直接continue!!!
贴代码。本人放个r1的代码攒rp好了~
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int d=1000001,n=2000001,r=1000000; int bit[n+3],A[100005],B[100005],del[100005]={0}; char op,buf[5000000],*p=buf,*o=buf; inline void upd(int x,int d){ for(;x<=n;x+=x&-x) bit[x]+=d;} inline int qry(int x){ int s=0; for(;x;x-=x&-x) s+=bit[x]; return s;} inline int getint(){ int s=0,f=1; while((*p!='-')&&(*p<'0'||*p>'9'))p++; if(*p=='-')f=-1,p++; while(*p>='0'&&*p<='9')s=s*10+*p++-48; return s*f; }inline char getop(){ while(*p!='Q'&&*p!='A'&&*p!='D')p++; return *p++; }inline void print(int x){ char str[30],*pt=str; if(!x)*o++=48; else{ while(x) *pt++=x%10+48,x/=10; while(pt--!=str)*o++=*pt;} }int main(){ fread(p,1,5000000,stdin); int q,a,b,k,i=0,t1,t2,An; q=getint(); for(int qq=1;qq<=q;qq++){ op=getop(); if(op=='A'){ a=getint(),t1=getint(),t2=getint(); b=t2-t1; ++i; A[i]=a; B[i]=b; if(a==0){ if(b<0)upd(1,1);} else if(b==0){ if(a<0) upd(1,1),upd(d,-1); else upd(1+d,1); }else if(b>0){ if(a>0){ An=b/a+1; if(-r<=An&&An<=r) upd(An+d,1); else if(An<-r) upd(1,1); }else{ An=b/(-a)+1; if(-r<=-An&&-An<=r) upd(1,1),upd(-An+d+1,-1); else if(-An>r) upd(1,1); } }else if(b<0){ if(a>0){ An=(-b-1)/a; if(-r<=-An&&-An<=r) upd(-An+d,1); else if(-An<-r) upd(1,1); }else{ An=(-b-1)/(-a); if(-r<=An&&An<=r) upd(1,1),upd(An+d+1,-1); else if(An>r) upd(1,1); } } }else if(op=='Q'){ k=getint(); print(qry(k+d));*o++='\n'; }else{ k=getint(); if(del[k])continue; del[k]=1; a=A[k]; b=B[k]; if(a==0){ if(b<0)upd(1,-1);} else if(b==0){ if(a<0) upd(1,-1),upd(d,1); else upd(1+d,-1); }else if(b>0){ if(a>0){ An=b/a+1; if(-r<=An&&An<=r) upd(An+d,-1); else if(An<-r) upd(1,-1); }else{ An=b/(-a)+1; if(-r<=-An&&-An<=r) upd(1,-1),upd(-An+d+1,1); else if(-An>r) upd(1,-1); } }else if(b<0){ if(a>0){ An=(-b-1)/a; if(-r<=-An&&-An<=r) upd(-An+d,-1); else if(-An<-r) upd(1,-1); }else{ An=(-b-1)/(-a); if(-r<=An&&An<=r) upd(1,-1),upd(An+d+1,1); else if(An>r) upd(1,-1); } } } }return fwrite(buf,1,o-buf,stdout),0; }
以及这是我贡献的一片红色。