您的位置:首页 > 其它

Bzoj 2038 莫队算法

2017-06-24 21:11 183 查看
拖了很久的莫队,直到看到了关于曼哈顿距离的解释才豁然开朗。手撸一个模板自用。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, m;
int c[50500];
ll f[50500];
int siz;
ll up;
ll u[50500];
ll d[50500];

struct que{
int l, r, id;
};

bool operator<(const que& a, const que& b){
return a.r<b.r;
}

vector<que>buck[300];

ll gcd(ll a, ll b){
if(b==0)return a;
return gcd(b, a%b);
}

void update(int p, int add){
int num=c[p];
up+=((f[num]+add)*(f[num]+add)-(f[num]*f[num])-add);
f[num]+=add;
}

int main()
{
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++){
scanf("%d", &c[i]);
}
siz=sqrt(n);
int l, r;
for(int i=1;i<=m;i++){
scanf("%d%d", &l, &r);
int p=(l-1)/siz+1;
buck[p].push_back((que){l, r, i});
}
for(int i=1;i<=siz+1;i++){
sort(buck[i].begin(), buck[i].end());
memset(f, 0, sizeof(f));
int l=1, r=0;
up=0;
for(int j=0;j<buck[i].size();j++){
if(l<buck[i][j].l){
for(;l<buck[i][j].l;l++){
update(l, -1);
}
}
if(l>buck[i][j].l){
for(;l>buck[i][j].l;l--){
update(l-1, 1);
}
}
if(r<buck[i][j].r){
for(;r<buck[i][j].r;r++){
update(r+1, 1);
}
}
if(r>buck[i][j].r){
for(;r>buck[i][j].r;r--){
update(r, -1);
}
}
ll len=buck[i][j].r-buck[i][j].l+1;
ll down=len*(len-1);
u[buck[i][j].id]=up;
d[buck[i][j].id]=down;
}
}
for(int i=1;i<=m;i++){
if(u[i]==0)printf("0/1\n");
else {
ll g=gcd(u[i], d[i]);
printf("%lld/%lld\n", u[i]/g, d[i]/g);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: