不要被题目给误导,这题根本不用树套树(我也不会),用线段树就可以完美解决。。。
比赛时也想到用线段树,但是想的太简单了,于是连wa两发。。然后一直到比赛结束也没有
想到正确思路,说到底我的线段树还是太菜了啊,感觉这题对线段树水平的要求比我的水平高了
两个等级,许老师的线段树水平比我高了至少三个等级,所以没费多大力就想到了正确思路。。
赛后许老师提醒了我几个关键点,发现这题只要构思好了其实并不是很难啊。,唉。。上代码:
#include#include #include #include using namespace std; int sumv1[400005],sumv2[400005],cnt[400005]; int T,n,q,c,p,ql,qr,p1,ql1,qr1,x,y; void update1(int o,int l,int r){ int m=(l+r)/2; if(l==r)sumv1[o]+=1; else{ if(p<=m)update1(o*2,l,m); else update1(o*2+1,m+1,r); sumv1[o]=sumv1[o*2]+sumv1[o*2+1]; } } int query1(int o,int l,int r){ int m=(l+r)/2; if(l>=ql&&r<=qr)return sumv1[o]; int ans=0; if(ql<=m)ans+=query1(o*2,l,m); if(qr>m)ans+=query1(o*2+1,m+1,r); return ans; } void update2(int o,int l,int r){ int m=(l+r)/2; if(l==r)sumv2[o]+=1; else{ if(p1<=m)update2(o*2,l,m); else update2(o*2+1,m+1,r); sumv2[o]=sumv2[o*2]+sumv2[o*2+1]; } } int query2(int o,int l,int r){ int m=(l+r)/2; if(l>=ql1&&r<=qr1)return sumv2[o]; int ans=0; if(ql1<=m)ans+=query2(o*2,l,m); if(qr1>m)ans+=query2(o*2+1,m+1,r); return ans; } int main(){ while(~scanf("%d%d",&n,&q)){ for(int i=0;i<=n*4;i++){ sumv1[i]=sumv2[i]=cnt[i]=0; } int s=0; while(q--){ scanf("%d",&c); if(c==1){ scanf("%d%d",&p,&p1); if(p==p1)cnt[p]++; update1(1,1,n); update2(1,1,n); s++; } else{ scanf("%d%d",&x,&y); ql=x+1,qr=n; ql1=1,qr1=y-1; int ans=s; if(qr>=ql)ans-=query1(1,1,n); if(qr1>=ql1)ans-=query2(1,1,n); if(y-x==2)ans+=cnt[x+1]; printf("%d\n",ans); } } } }