莫队算法练习题
前导知识
:
1. 数列找不同
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n,q;
int a[N],vis[N],s[N],now,ans[N];
int l,r;
struct node{
int l,r,id;
bool operator <(const node b) const{
return s[l]==s[b.l]?r<b.r:s[l]<s[b.l];
}
}Q[N];
inline int read(){
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-f;ch=getchar();}
while (ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void del(int x){vis[a[x]]--;if (!vis[a[x]]) now--;}
inline void add(int x){vis[a[x]]++;if (vis[a[x]]==1) now++;}
int main(){
n=read();q=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
for(int i=1;i<=q;i++){
Q[i].l=read();Q[i].r=read();Q[i].id=i;
}
int si=sqrt(n);
int num=ceil((double)n/si);
for(int i=1;i<=num;i++)
for(int j=(i-1)*si+1;j<=i*si;j++)
s[j]=i;
sort(Q+1,Q+q+1);
for(int i=1;i<=q;i++){
while(l<Q[i].l) del(l++);
while(l>Q[i].l) add(--l);
while(r<Q[i].r) add(++r);
while(r>Q[i].r) del(r--);
if(now==Q[i].r-Q[i].l+1) ans[Q[i].id]=1;
}
for(int i=1;i<=q;i++){
if(!ans[i]) printf("No\n");
else printf("Yes\n");
}
return 0;
}
2. 小z的袜子
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 50005;
int n, m, maxn;
int c[N];
long long sum;
int cnt[N];
long long ans1[N], ans2[N];
struct query{
int l, r, id;
bool operator<(const query &x) const {
if (l / maxn != x.l / maxn) return l < x.l;
return (l / maxn) & 1 ? r < x.r : r > x.r;
}
}a[N];
void add(int i) {
sum += cnt[i];
cnt[i]++;
}
void del(int i) {
cnt[i]--;
sum -= cnt[i];
}
long long gcd(long long a, long long b) {
return b ? gcd(b, a % b) : a;
}
int main() {
scanf("%d%d", &n, &m);
maxn = sqrt(n);
for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
for (int i = 0; i < m; i++) scanf("%d %d", &a[i].l, &a[i].r), a[i].id = i;
sort(a, a + m);
for (int i = 0, l = 1, r = 0; i < m; i++) {
if (a[i].l == a[i].r) {
ans1[a[i].id] = 0, ans2[a[i].id] = 1;
continue;
}
while (l > a[i].l) add(c[--l]);
while (r < a[i].r) add(c[++r]);
while (l < a[i].l) del(c[l++]);
while (r > a[i].r) del(c[r--]);
ans1[a[i].id] = sum;
ans2[a[i].id] = (long long)(r - l + 1) * (r - l) / 2;
}
for (int i = 0; i < m; i++) {
if (ans1[i] != 0) {
long long g = gcd(ans1[i], ans2[i]);
ans1[i] /= g, ans2[i] /= g;
} else
ans2[i] = 1;
printf("%lld/%lld\n", ans1[i], ans2[i]);
}
return 0;
}