您的位置:首页 > 其它

[BZOJ 3295]动态逆序对

2016-03-15 21:14 225 查看
每次删一个数,询问逆序对数量

分块大法好,暴力出奇迹

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define maxn 100010
#define Size 500
using namespace std;

void read(int &num){
num = 0;char ch = getchar();
for(; ch < '!'; ch = getchar());
for(; ch > '!'; ch = getchar())
num = num * 10 + ch - 48;
}

int n, m;

int t[maxn], pos[maxn], here[maxn];

bool bo[maxn];

const int inf = 0x7fffffff;

struct block{
int a[Size], sum, l, r, cnt;
void build(int id){
cnt = 0;
for(int i = l; i <= r; i ++){
a[++ cnt] = t[i];
pos[i] = id;
here[t[i]] = id;
}
sort(a + 1, a + 1 + cnt);
}

void rebuild(int p){
for(int i = 1; i <= cnt; i ++)
if(a[i] == p){
a[i] = inf;
break;
}
sort(a + 1, a + 1 + cnt);
cnt --;bo[p] = true;
}

int small(int p){
if(cnt == 0)return 0;
int t = lower_bound(a + 1, a + 1 + cnt, p) - a;
if(a[t] > p)t --;
if(t > cnt)return cnt;
return t;
}

int big(int p){
if(cnt == 0)return 0;
int t = lower_bound(a + 1, a + 1 + cnt, p) - a;
if(a[t] > p)t --;
if(t == 0)return cnt;
if(t > cnt)return 0;
return cnt - t;
}

int bruteforce(int p){
int flag = true;
int ret = 0;
for(int i = l; i <= r; i ++){
if(bo[t[i]])continue;
if(t[i] == p){flag = false;continue;}
if(flag && t[i] > p)ret ++;
if(!flag && t[i] < p)ret ++;
}
return ret;
}
}b[Size];

struct BIT{
int t[maxn];
int lowbit(int i){
return i & -i;
}
void update(int pos, int val){
for(int i = pos; i; i -= lowbit(i))
t[i] += val;
}
int ask(int pos){
int ret = 0;
for(int i = pos; i <= n; i += lowbit(i))
ret += t[i];
return ret;
}
}T;

long long getanti(){
long long ans = 0;
for(int i = 1; i <= n; i ++){
ans += T.ask(t[i]);
T.update(t[i], 1);
}
return ans;
}

int main(){
read(n), read(m);
for(int i = 1; i <= n; i ++)
read(t[i]);
int blo = sqrt(n);
if(blo * blo < n)blo ++;
for(int i = 1; i <= blo; i ++){
int L = (i - 1) * blo + 1, R = i * blo;
R = min(R, n);
b[i].l = L, b[i].r = R;
b[i].build(i);
if(R == n){
blo = i;
break;
}
}
long long ans = getanti();

int x;
for(int i = 1; i <= m; i ++){
printf("%lld\n", ans);
read(x);
int t = here[x];
ans -= b[t].bruteforce(x);
for(int j = 1; j < t; j ++)
ans -= b[j].big(x);
for(int j = t + 1; j <= blo; j ++)
ans -= b[j].small(x);
b[t].rebuild(x);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分块