思想:
在队列里通过l,r 更新区间的答案;
不过要分 根号n 的版块 进行(特殊)排序;
代码:
struct dian{ int l,r,pos(版块),id; bool operator <(const dian &t)const //特殊排序 { if(pos==t.pos) return r<t.r; return l<t.l; } }p[M];
例题 :
给定n个数字序列a ,a ,...,a 和许多d查询。d查询是一对(i,j)(1≤i≤j≤n)。对于每个d查询(i,j),您必须返回子序列a ,a,...,a 中不同元素的数量。
输入项
- 第1行:n(1≤n≤30000)。
- 第2行:n个一个,一个,...,A (1≤一个 ≤10 )。
- 第3行:d查询的数量q(1≤q≤200000)。
- 在接下来的q行中,每行包含2个代表d查询的数字i,j(1≤i≤j≤n)。
输出量
- 对于每个d查询(i,j),在一行中打印子序列a ,a,...,中不同元素的数量。
例
输入项 5 1 1 2 1 3 3 1 5 2 4 3 5 输出量 3 2 3
代码:
#include <bits/stdc++.h> using namespace std; const long long M=2000000; struct dian{ long long l,r,pos,id,ans; bool operator <(const dian &t)const { if(pos==t.pos) return r<t.r; return l<t.l; } }p[M]; long long n,m,val[M],cent[M],trmp,ans2[M]; long long main(){ scanf("%d",&n); for(register long long i=1;i<=n;i++) { scanf("%d",&val[i]); } long long d=long long(0.5+sqrt(n)); // cout<<d<<endl; scanf("%d",&m); for(register long long i=1;i<=m;i++) { long long a,b; scanf("%d%d",&a,&b); p[i].pos=a/d; p[i].id=i; p[i].l=a; p[i].r=b; } sort(p+1,p+m+1); // cout<<"yes"<<endl; for(register long long i=p[1].l;i<=p[1].r;i++) { cent[val[i]]++; if(cent[val[i]]==1) p[1].ans++; } // cout<<"yes"<<endl; ans2[p[1].id]=p[1].ans; for(register long long i=2;i<=m;i++) { trmp=p[i-1].ans; long long l=p[i-1].l; long long r=p[i-1].r; while(l<p[i].l) { cent[val[l]]--; if(cent[val[l]]==0) // trmp--; l++; } while(l>p[i].l) { l--; cent[val[l]]++; if(cent[val[l]]==1) trmp++; } while(r<p[i].r) { r++; cent[val[r]]++; if(cent[val[r]]==1) trmp++; } while(r>p[i].r) { cent[val[r]]--; if(cent[val[r]]==0) trmp--; r--; } p[i].ans=trmp; ans2[p[i].id]=trmp; } // cout<<"yes"<<endl; for(register long long i=1;i<=m;i++) { prlong longf("%d\n",ans2[i]); } return 0; }