hdu 4638 树状数组
思路:将查询区间按右节点的升序排列,然后插入第i个数的时候,若nun[i]+1已经插入,那么就update(pre[num[i]+1],-1);pre[]表示的是该数的位置。同样若
num[i]-1存在就update(pre[num[i]-1],-1);因为他么与num[i]属于一组,故只需一个存在就行。当查询的右边界r等于i时,只需对其左边界求和就行,Sum(qt[j].l)。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define Maxn 100010 #define lowbit(x) (x&(-x)) using namespace std; int C[Maxn],pre[Maxn],n,ans[Maxn]; struct QT{ int l,r,i; int operator <(const QT &temp) const { return r<temp.r; } }qt[Maxn]; int Sum(int pos) { int sum=0; while(pos<=n)//求和与更新反向的树状数组 { sum+=C[pos]; pos+=lowbit(pos); } return sum; } void update(int pos,int val) { while(pos) { C[pos]+=val; pos-=lowbit(pos); } } int main() { int t,m,i,j,num[Maxn]; scanf("%d",&t); while(t--) { memset(C,0,sizeof(C)); memset(pre,0,sizeof(pre)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",num+i),pre[num[i]]=i; for(i=1;i<=m;i++) { scanf("%d%d",&qt[i].l,&qt[i].r); qt[i].i=i; } sort(qt+1,qt+1+m); j=1; for(i=1;i<=n;i++) { if(j>m) break; if(num[i]<n&&pre[num[i]+1]<i) update(pre[num[i]+1],-1); if(num[i]>1&&pre[num[i]-1]<i) update(pre[num[i]-1],-1); update(i,1); while(qt[j].r==i&&j<=m) { ans[qt[j].i]=Sum(qt[j].l); j++; } } for(i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }