题意:给出一个数组,每次查询l,r,看区间内能分成几个连续的数列也即时求 求一个区间中连续ID区间的个数。需要离线处理所有查询。我们从左往右扫描,依次考虑右端点为i的询问,设dp[l]为区间[l,i]的连续区间个数,po[i]为i出现的位置,若还未出现,则为 0,设我们当前考虑的右端点为a[i],首先我们假设a[i]不能和区间[1,i-1]中的任何一个数分到一组,则我们要将dp[1]到dp[i-1]全 部加1,然后考虑po[a[i]+1]是否不为0,若不为0则说明a[i]-1已经在前面出现,则我们需要将dp[1]到dp[po[a[i]+1]]全 部减一个1,因为a[i]可以和a[i]+1分为一组,则我们之前加的1是多余的。对于a[i]-1的情况同理。树状数组版:#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; #define nn 100010 int tree[nn],a[nn],pos[nn],sol[nn]; struct node { int l,r,id; }s[nn]; int n,m; bool cmp(node a,node b) { return a.r<b.r; } int lowbit(int x) { return x&(-x); } int sum(int x) { int ans=0; while(x>0) { ans+=tree[x]; x-=lowbit(x); } return ans; } void add(int x,int val) { while(x<=n) { tree[x]+=val; x+=lowbit(x); } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=1;i<=m;i++) { scanf("%d%d",&s[i].l,&s[i].r); s[i].id=i; } memset(tree,0,sizeof(tree)); sort(s+1,s+m+1,cmp); int j=1; for(int i=1;i<=n;i++) { add(i,1); if(a[i]<n && pos[a[i]+1]<i) add(pos[a[i]+1],-1); if(a[i]>1 && pos[a[i]-1]<i) add(pos[a[i]-1],-1); while(j<=m && s[j].r==i) { sol[s[j].id]=sum(s[j].r)-sum(s[j].l-1); j++; } } for(int i=1;i<=m;i++) printf("%d\n",sol[i]); } return 0; }
线段树版:#include<stdio.h> #include<string.h> #include<math.h> #include<queue> #include<vector> #include<iostream> #include<string> #include<set> #include<map> #include<algorithm> using namespace std; #pragma comment(linker, "/STACK:1024000000,1024000000") #define nn 100010 #define LL long long #define ULL unsiged long long #define mod 0x7fffffff #define inf oxfffffffffff #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 int a[nn],loc[nn],pos[nn]; struct node { int l,r,num; }tree[nn<<2]; struct seg { int l,r,id; }s[nn]; bool cmp(seg a,seg b) { return a.r<b.r; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].num=0; if(l==r) return; int mid=(l+r)>>1; build(lson); build(rson); } void pushup(int rt) { tree[rt].num=tree[rt<<1].num+tree[rt<<1|1].num; } void updata(int l,int r,int val,int rt) { if(l==tree[rt].l && r==tree[rt].r) { tree[rt].num+=val; return; } int mid=(tree[rt].l+tree[rt].r)>>1; if(r<=mid) updata(l,r,val,rt<<1); else if(l>mid) updata(l,r,val,rt<<1|1); else { updata(l,mid,val,rt<<1); updata(l,mid+1,val,rt<<1|1); } pushup(rt); } int query(int l,int r,int rt) { if(tree[rt].l==l && tree[rt].r==r) return tree[rt].num; int mid=(tree[rt].l+tree[rt].r)>>1; if(r<=mid) return query(l,r,rt<<1); else if(l>mid) return query(l,r,rt<<1|1); else return query(l,mid,rt<<1)+query(mid+1,r,rt<<1|1); } int main() { int n,m,t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); loc[a[i]]=i; } for(int i=1;i<=m;i++) { scanf("%d%d",&s[i].l,&s[i].r); s[i].id=i; } sort(s+1,s+m+1,cmp); build(1,n,1); int j=1; for(int i=1;i<=n;i++) { updata(i,i,1,1); if(a[i]<n && loc[a[i]+1]<i) updata(loc[a[i]+1],loc[a[i]+1],-1,1); if(a[i]>1 && loc[a[i]-1]<i) updata(loc[a[i]-1],loc[a[i]-1],-1,1); while(j<=m && s[j].r==i) { pos[s[j].id]=query(s[j].l,s[j].r,1); j++; } } for(int i=1;i<=m;i++) printf("%d\n",pos[i]); } return 0; }