1. 程式人生 > >[LOJ]#6164. 「美團 CodeM 初賽 Round A」數列互質 莫隊

[LOJ]#6164. 「美團 CodeM 初賽 Round A」數列互質 莫隊

題解:

這題只需要用到一個性質就行了:不同的出現次數最多隻有根號種,因為 1 + 2 + . . . + x

= ( x 1 ) x 2
1+2+...+x={{(x-1)x}\over2}
然後直接莫隊暴力即可。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=50010;
const int inf=2147483647;
int read()
{
	int x=0,f=1;char ch=
getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f; } int gcd(int a,int b) { if(!a)return b; return gcd(b%a,a); } int n,m,a[Maxn],bel[Maxn],cnt[Maxn],cc[Maxn],nxt[Maxn],lst[Maxn],st=-1; struct Query{int l,r,k,id;}q[Maxn]; bool cmp(Query a,Query b) { if(bel[a.l]!=bel[b.l])return a.l<b.l; return a.r<b.r; } void del(int x) { if(!x)return; cc[x]--; if(cc[x])return; if(lst[x]!=-1)nxt[lst[x]]=nxt[x]; else st=nxt[x]; if(nxt[x]!=-1)lst[nxt[x]]=lst[x]; } void ins(int x) { if(!x)return; if(!cc[x]) { nxt[x]=st; if(st!=-1)lst[st]=x; st=x;lst[x]=-1; } cc[x]++; } void w(int x,int op) { del(cnt[x]); cnt[x]+=op; ins(cnt[x]); } int ans[Maxn]; int main() { n=read(),m=read(); int sz=(int)sqrt(n); for(int i=1;i<=n;i++)a[i]=read(),bel[i]=(i-1)/sz+1; for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].k=read(),q[i].id=i; sort(q+1,q+1+m,cmp); int l=1,r=0; for(int i=1;i<=m;i++) { while(l>q[i].l)w(a[--l],1); while(r<q[i].r)w(a[++r],1); while(l<q[i].l)w(a[l++],-1); while(r>q[i].r)w(a[r--],-1); int t=0; for(int j=st;j!=-1;j=nxt[j]) if(gcd(j,q[i].k)==1)t+=cc[j]; ans[q[i].id]=t; } for(int i=1;i<=m;i++)printf("%d\n",ans[i]); }