[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;
}
分块大法好,暴力出奇迹
#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;
}
相关文章推荐
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- Codeforces538F A Heap of Heaps【分块+差分求前缀和】
- 大矩阵的分块乘法及matlab实现
- Hadoop分块和分片
- bzoj-2741 L
- bzoj-3585 mex
- bzoj-2051 A Problem For Fun
- 算法马拉松8(差和问题)
- 1290 Counting Diff Pairs
- 【Violet 6】【BZOJ2724】蒲公英
- 【BZOJ4320】Homework
- 【BZOJ4216】Pig
- 【BZOJ2741】FOTILE模拟赛 L
- [2009国家集训队]小Z的袜子(hose) 分块做法
- NBUT 1457 分块
- codeforces #307 E. GukiZ and GukiZiana (分块)
- Codeforces Round #307 (Div. 2)E. GukiZ and GukiZiana(分块)
- 【分块】 CF 551 E GukiZ and GukiZiana
- Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana (分块)
- Codeforces Gym 100589A Queries on the Tree(树状数组+分块)