P1997 faebdc 的烦恼+P7764 [COCI 2016/2017 #5] Poklon(莫队)
P1997 faebdc 的烦恼 - 洛谷


题目大意:给你一个数组,然后进行q次询问,每次输出区间[l,r]中数字出现最多的次数。
思路:很板的莫队了。这里的add函数写得还是很妙的,cnt[x]表示x出现的次数,sum[cnt[x]]表示出现cnt[x]次数的数字个数。每次进行相应add和sub操作时更新这两个数组以及结果。
Code:
int n,q;
int pos[N],ans[N],cnt[N],a[N],sum[N];
unordered_map<int,int> mp;
int res,m,num;
struct node{int l,r,id;
}tr[N];void add(int x)
{sum[cnt[x]]--;cnt[x]++;sum[cnt[x]]++;if(res<cnt[x]) res=cnt[x];
}void sub(int x)
{sum[cnt[x]]--;cnt[x]--;sum[cnt[x]]++;if(res==cnt[x]+1&&!sum[cnt[x]+1]){res=cnt[x];}
}
void solve()
{cin>>n>>q;int sz=sqrt(n);for(int i=1;i<=n;i++) {cin>>a[i];if(!mp[a[i]]) mp[a[i]]=++num;pos[i]=i/sz;}m=*max_element(a+1,a+1+n);for(int i=1;i<=q;i++){int l,r;cin>>l>>r;tr[i]={l,r,i};}sort(tr+1,tr+q+1,[&](node x,node y){return (pos[x.l]==pos[y.l]?x.r<y.r:pos[x.l]<pos[y.l]);});int l=1,r=0;for(int i=1;i<=q;i++){while(tr[i].l<l) add(mp[a[--l]]);while(tr[i].r>r) add(mp[a[++r]]);while(tr[i].l>l) sub(mp[a[l++]]);while(tr[i].r<r) sub(mp[a[r--]]);ans[tr[i].id]=res;}for(int i=1;i<=q;i++) cout<<ans[i]<<endl;}
P7764 [COCI 2016/2017 #5] Poklon - 洛谷
题目大意:给定一个长度为n的数组,进行q次询问,每次输出[l,r]中出现次数为2的数字个数。
思路:与上题一致,但这道题要提前将a[i]=mp[a[i]],不然后面每次询问进行四次map的查找会TLE一个点。
Code:
int n,q,sz;
int pos[N],cnt[N],a[N],sum[N],res,ans[N];
unordered_map<int,int> mp;
int num;
struct node{int l,r,id;
}tr[N];void add(int x)
{sum[cnt[x]]--;cnt[x]++;sum[cnt[x]]++;
}void sub(int x)
{sum[cnt[x]]--;cnt[x]--;sum[cnt[x]]++;
}void solve()
{cin>>n>>q;sz=sqrt(n);for(int i=1;i<=n;i++) {cin>>a[i];if(!mp[a[i]]) mp[a[i]]=++num;a[i]=mp[a[i]];pos[i]=i/sz;}for(int i=1;i<=q;i++){int l,r;cin>>l>>r;tr[i]={l,r,i};}sort(tr+1,tr+q+1,[&](node x,node y){return pos[x.l]==pos[y.l]?x.r<y.r:pos[x.l]<pos[y.l];});int l=1,r=0;for(int i=1;i<=q;i++){while(tr[i].l<l) add(a[--l]);while(tr[i].r>r) add(a[++r]);while(tr[i].l>l) sub(a[l++]);while(tr[i].r<r) sub(a[r--]);ans[tr[i].id]=sum[2];}for(int i=1;i<=q;i++) cout<<ans[i]<<endl;
}
