BZOJ-2038 小Z的袜子(hose)
小Z的袜子(hose)
莫队 板子题
在 add 和 del 上边得先删除原本的,再添加新的
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define endl '\n'
typedef long long ll;
const int maxn = 5e4 + 10;
int num[maxn], pos[maxn];
ll up[maxn], down[maxn], ans = 0, cnt[maxn];
struct node
{
int l, r, id;
node(){}
node(int _l, int _r, int _id){id = _id; l = _l; r = _r;}
}seg[maxn];
bool cmp(const node& a, const node& b)
{
return pos[a.l] ^ pos[b.l] ? pos[a.l] < pos[b.l] : (pos[a.l] & 1 ? a.r > b.r : a.r < b.r);
}
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
inline void add(int x)
{
int now = num[x];
if(cnt[now]) ans -= cnt[now] * (cnt[now] - 1) / 2;
cnt[now]++;
ans += cnt[now] * (cnt[now] - 1) / 2;
}
inline void del(int x)
{
int now = num[x];
ans -= cnt[now] * (cnt[now] - 1) / 2;
cnt[now]--;
if(cnt[now]) ans += cnt[now] * (cnt[now] - 1) / 2;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for(int i=1; i<=n; i++) cin >> num[i];
for(int i=0; i<m; i++)
{
int x, y;
cin >> x >> y;
seg[i] = node(x, y, i);
}
int t = sqrt(n);
for(int i=0; i<=n; i++) pos[i] = i / t;
sort(seg, seg + m, cmp);
int l = 1, r = 0;
for(int i=0; i<m; i++)
{
while(seg[i].l < l) add(--l);
while(seg[i].r > r) add(++r);
while(seg[i].l > l) del(l++);
while(seg[i].r < r) del(r--);
up[seg[i].id] = ans;
ll x = r - l + 1;
down[seg[i].id] = x * (x - 1) / 2;
}
for(int i=0; i<m; i++)
{
if(up[i] == 0) {cout << 0 << "/" << 1 << endl; continue;}
ll x = gcd(down[i], up[i]);
up[i] /= x;
down[i] /= x;
cout << up[i] << "/" << down[i] << endl;
}
return 0;
}