BZOJ 3295: [Cqoi2011]动态逆序对 分块大法好
来源:互联网 发布:啊哈 算法 epub 编辑:程序博客网 时间:2024/06/07 01:57
题目链接:这里
解法:树套树 和 CDQ不会写,分块暴力大法好。
我们可以把原序列a[]分成个块,每个块有个数。然后维护一个b[],b[]中的每一个块都是一个单调递增的序列。
当前要删除的数为x,所在的块是k,那我们分两种情况做:
1.对于k号块,直接在a[]的k号块中枚举求逆序对,复杂度为。
2.对于除了k号块以外的每一个块,利用b[]二分求x在当前块中产生的逆序对数,复杂度为O(nsqrt(n))
然后删除这个数,把b[]中相对应的数变为0,把这个块重新排序。
因为我们要保证每个块的大小不变,并且每个数所在的块的编号也不变,所以我们在删除的时候不能直接删除。
既然不能直接删除,我们就得搞一些东西来维护。
在计算第一步的时候,我们开一个bool数组f[i],表示i这个数有没有被删掉,然后枚举的时候判断一下。
在计算第二步的时候,我们开一个数组sum[],sum[i]表示第i个块里删除了多少个数。这样的话,如果我们在计算的时候这个
块里产生了t对逆序对,而已经被删除的数都变成0,所以每个0都会产生一个逆序对,那么不算上已经被删除的实际只有
t-sum[i]个逆序对。
然后就做完啦。
///BZOJ 3295 动态逆序对#include <bits/stdc++.h>using namespace std;typedef long long LL;//LL ans;const int maxn = 200010;int n, m, x, y, num, block, a[maxn], b[maxn], tmp[maxn], belong[maxn], l[maxn], r[maxn], sum[maxn], id[maxn];bool f[maxn];LL ans;int c[maxn];inline int lowbit(int x){ return x&-x;}void add(int x, int v){ for(int i=x; i<=n; i+=lowbit(i)) c[i]+=v;}int query(int x){ int res=0; for(int i=x; i; i-=lowbit(i)) res+=c[i]; return res;}void init(){ scanf("%d %d", &n,&m); block = sqrt(n); num = n/block; if(n%block) num++; for(int i=1; i<=num; i++) l[i]=(i-1)*block+1,r[i]=i*block; r[num]=n; for(int i=1; i<=n; i++) belong[i]=(i-1)/block+1; for(int i=1; i<=n; i++) scanf("%d", &a[i]), tmp[i]=a[i], id[a[i]]=i; ans = 0; for(int i=1; i<=n; i++){ add(a[i],1); ans+=1LL*(i-query(a[i])); } for(int i=1; i<=n; i++) b[i]=a[i]; for(int i=1; i<=num; i++) sort(b+l[i],b+r[i]+1); for(int i=1; i<=n; i++) f[i]=1,sum[i]=0;}int query2(int pos, int val){ int low, high, ret; low = l[pos]; high = r[pos]; ret = r[pos]; while(low <= high){ int mid = (low+high)/2; if(b[mid]<=val) ret=mid,low=mid+1; else high=mid-1; } if(b[ret]>val) return l[pos]-1; else return ret;}int main(){ init(); while(m--){ printf("%lld\n", ans); scanf("%d", &y); x = id[y]; int k = belong[x]; for(int i=1; i<k; i++){ ans-=(r[i]-query2(i,a[x])); } for(int i=k+1; i<=num; i++){ ans-=query2(i,a[x])-l[i]+1-sum[i]; } for(int i=l[k]; i<x; i++){ if(f[a[i]]&&a[i]>a[x]) ans--; } for(int i=x+1; i<=r[k]; i++){ if(f[a[i]]&&a[i]<a[x]) ans--; } int pos = query2(k,a[x]); b[pos]=0; sum[k]++; f[a[x]]=0; sort(b+l[k],b+r[k]+1); } return 0;}
阅读全文
0 0
- BZOJ 3295: [Cqoi2011]动态逆序对 分块大法好
- [BZOJ 3295] Cqoi2011 动态逆序对
- 【BZOJ 3295】 [Cqoi2011]动态逆序对
- BZOJ 3295 [Cqoi2011]动态逆序对
- BZOJ 3295 [CQOI2011] 动态逆序对
- BZOJ 3295: [Cqoi2011]动态逆序对
- 【BZOJ 3295】[Cqoi2011]动态逆序对
- bzoj 3295 [Cqoi2011]动态逆序对
- BZOJ 3295 [Cqoi2011]动态逆序对
- [bzoj]3295: [Cqoi2011]动态逆序对 主席树
- 主席树初探 & bzoj 3295: [Cqoi2011] 动态逆序对 题解
- bzoj 3295: [Cqoi2011]动态逆序对(树套树)
- bzoj 3295: [Cqoi2011]动态逆序对 【cdq分治】
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- BZOJ 3295 [Cqoi2011] 动态逆序对 CDQ分治题解
- 【BZOJ】3295 [Cqoi2011]动态逆序对 树状数组+线段树
- 3295: [Cqoi2011]动态逆序对
- 3295: [Cqoi2011]动态逆序对
- BZOJ3924: [Zjoi2015]幻想乡战略游戏 动态树分治
- 堆和栈的区别和联系
- 字符串替换
- C语言文件操做
- JDBC的学习 一
- BZOJ 3295: [Cqoi2011]动态逆序对 分块大法好
- 港股通收市竞价交易机制科普
- jdbc介绍
- 刷题--顺时针打印矩阵
- Leetcode 303 Range Sum Query
- 机房重构——全局变量
- rel、href、src、url的区别
- Size_t
- day1