Codeforces Round #136
B题和那个多校比赛的一个题目有点像,大意都是求一段序列的满足某个元素出现次数为一个固定值的个数,都差不多
我用的线段树实现的,写的太龊了
#include <iostream> #include <cstdlib> #include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100010; vector<int> g[maxn]; int d[maxn<<2],a[maxn],b[maxn],ans[maxn]; struct Node { int l,r,id; }q[maxn]; void update(int p,int val,int l,int r,int rt) { if(l==r) { d[rt]=val;return; } int m=(l+r)>>1; if(p<=m) update(p,val,lson); else update(p,val,rson); d[rt]=d[rt<<1]+d[rt<<1|1]; } int query(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) return d[rt]; int m=(l+r)>>1,ret1=0,ret2=0; if(L<=m) ret1=query(L,R,lson); if(R>m) ret2=query(L,R,rson); return ret1+ret2; } int cmp(Node a,Node b) { return a.r < b.r; } int bin(int key,int l,int r) { while(l<=r) { int m=(l+r)>>1; if(b[m]==key) return m; else if(b[m]>key) r=m-1; else l=m+1; } } int main() { int n,m,l,r; while(scanf("%d%d",&n,&m)==2) { for(int i=0;i<n;i++) scanf("%d",&a[i]),b[i]=a[i],g[i].clear(); memset(d,0,sizeof(d)); sort(b,b+n); int k=unique(b,b+n)-b; for(int i=0;i<m;i++) { scanf("%d%d",&l,&r); q[i].l=l-1,q[i].r=r-1; q[i].id=i; } sort(q,q+m,cmp); int cnt=0; for(int i=0;i<n;i++) { int p=bin(a[i],0,k-1); if(g[p].size()<a[i]-1){ g[p].push_back(i); }else{ g[p].push_back(i); int sz=g[p].size(); update(g[p][sz-a[i]],1,0,n-1,1); if(sz>=a[i]+1) update(g[p][sz-a[i]-1],-1,0,n-1,1); if(sz>=a[i]+2) update(g[p][sz-a[i]-2],0,0,n-1,1); } while(cnt<m&&q[cnt].r==i){ ans[q[cnt].id]=query(q[cnt].l,q[cnt].r,0,n-1,1); cnt++; } if(cnt==m) break; } for(int i=0;i<m;i++) printf("%d\n",ans[i]); } return 0; }
还有其他的方法
不过这种方法要比线段树慢很多
#include <iostream> #include <cstdlib> #include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int maxn=100010; int chd[500][maxn],a[maxn],b[maxn],t[maxn]; int main() { int n,m,l,r; while(scanf("%d%d",&n,&m)==2) { memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) { scanf("%d",&t[i]); if(t[i]<=n) a[t[i]]++; } int tot=0; for(int i=1;i<=n;i++) if(a[i]>=i){ b[tot]=i; for(int j=1;j<=n;j++) chd[tot][j]=chd[tot][j-1]+(t[j]==i); tot++; } while(m--){ scanf("%d%d",&l,&r); int ans=0; for(int i=0;i<tot;i++) if(chd[i][r]-chd[i][l-1]==b[i]) ans++; printf("%d\n",ans); } } return 0; }