题意:询问不同区间不同值的个数
//思路1 700+ms #include<iostream> #include<string> #include<algorithm> using namespace std; #define CL(a,b) memset(a,b,sizeof(a)) const int M(100010); const int N(1020); int f[N],r[M]; struct data{ int x,sub; }a[M]; struct dat{ int l,r; int sub; }ans[N]; int vis[M]; bool cmp(data x,data y) { return x.x<y.x; } bool cm(dat x,dat y ) { return x.l<y.l||(x.l==y.l&&x.r<y.r); } int main() { int m,i,n,j,q; while(scanf("%d",&m)!=EOF) { for(i=1;i<=m;i++) { scanf("%d",&a[i].x); a[i].sub=i; } sort(a+1,a+m+1,cmp); r[a[1].sub]=0; for(i=2,j=0;i<=m;i++)//离散化 { if(a[i-1].x==a[i].x) r[a[i].sub]=j; else { j++; r[a[i].sub]=j; } } scanf("%d",&q); for(i=0;i<q;i++) { scanf("%d%d",&ans[i].l,&ans[i].r); ans[i].sub=i; } sort(ans,ans+q,cm); CL(f,0); CL(vis,0);//vis记录出现个数 for(i=0;i<q;i++) { if(i==0) { CL(vis,0); for(j=ans[i].l;j<=ans[i].r;j++) { if(!vis[r[j]]) f[ans[i].sub]++; vis[r[j]]++; } continue; } if(ans[i].r<ans[i-1].r) { if((ans[i].l-ans[i-1].l+ans[i-1].r-ans[i].r)>(ans[i].r-ans[i].l)) { CL(vis,0); for(j=ans[i].l;j<=ans[i].r;j++) { if(!vis[r[j]]) f[ans[i].sub]++; vis[r[j]]++; } } else { f[ans[i].sub]=f[ans[i-1].sub]; for(j=ans[i-1].l;j<ans[i].l;j++) { vis[r[j]]--; if(vis[r[j]]==0) f[ans[i].sub]--; } for(j=ans[i].r+1;j<=ans[i-1].r;j++) { vis[r[j]]--; if(vis[r[j]]==0) f[ans[i].sub]--; } } } else { if((ans[i].l-ans[i-1].l)>(ans[i-1].r-ans[i].l)) { CL(vis,0); for(j=ans[i].l;j<=ans[i].r;j++) { if(!vis[r[j]]) f[ans[i].sub]++; vis[r[j]]++; } } else { f[ans[i].sub]=f[ans[i-1].sub]; for(j=ans[i-1].l;j<ans[i].l;j++) { vis[r[j]]--; if(vis[r[j]]==0) f[ans[i].sub]--; } for(j=ans[i-1].r+1;j<=ans[i].r;j++) { if(!vis[r[j]]) f[ans[i].sub]++; vis[r[j]]++; } } } } for(i=0;i<q;i++) printf("%d\n",f[i]); } }//参考: http://blog.csdn.net/sqplfh/article/details/6840996
具体思路:先把N个保存下来,进行离散,然后用就可以用flag记录某个数前面出现的位置,再把询问保存下来,按右端点排序。
对N个数依次处理,删除该数前面出现的,在当前位置插入该数。当处理到第i个位置的数,且询问的右端点也为i是,统计个数。
// 300+ms 线段树优化 #include<iostream> #include<string> #include<algorithm> using namespace std; #define CL(a,b) memset(a,b,sizeof(a)) #define MID(a,b) (a+b)>>1 const int M(100010); const int N(1020); int tree[M<<2],r[M],f[N]; struct data{ int x,sub; }a[M]; struct dat{ int l,r; int sub; }ans[N]; int vis[M]; bool cmp(data x,data y) { return x.x<y.x; } bool cm(dat x,dat y ) { return x.r<y.r; } inline void pushup(int t) { tree[t]=tree[t<<1]+tree[t<<1|1]; } void insert(int t,int x,int val,int l,int r) { if(l==r) { tree[t]=val; return; } int mid=MID(l,r); if(x<=mid) insert(t<<1,x,val,l,mid); if(x>mid) insert(t<<1|1,x,val,mid+1,r); pushup(t); } int query(int t,int ql,int qr,int l,int r) { if(ql<=l&&qr>=r) return tree[t]; int mid=MID(l,r); if(qr<=mid) return query(t<<1,ql,qr,l,mid); else if(ql>mid) return query(t<<1|1,ql,qr,mid+1,r); else return query(t<<1,ql,qr,l,mid)+query(t<<1|1,ql,qr,mid+1,r); } int main() { int m,i,n,j,q; while(scanf("%d",&m)!=EOF) { for(i=1;i<=m;i++) { scanf("%d",&a[i].x); a[i].sub=i; } sort(a+1,a+m+1,cmp); r[a[1].sub]=0; for(i=2,j=0;i<=m;i++) { if(a[i-1].x==a[i].x) r[a[i].sub]=j; else { j++; r[a[i].sub]=j; } } scanf("%d",&q); for(i=0;i<q;i++) { scanf("%d%d",&ans[i].l,&ans[i].r); ans[i].sub=i; } sort(ans,ans+q,cm); CL(vis,-1); CL(tree,0); for(i=1,j=0;i<=m&&j<q;i++) { if(vis[r[i]]!=-1) { insert(1,vis[r[i]],0,1,m); } insert(1,i,1,1,m); vis[r[i]]=i; while(i==ans[j].r) { f[ans[j].sub]=query(1,ans[j].l,ans[j].r,1,m); j++; //printf("%d\n",tree[1]); } } for(i=0;i<q;i++) printf("%d\n",f[i]); } }