• 【CQOI2011】动态逆序对


    分析

    近乎裸的 (cdq) 分治数点问题
    我们考虑一个数被删去,它对删后区间逆序对个数的影响就是减去现存序列中前面比它大的个数再减去现存序列中后面比它小的个数
    那么我们考虑如何处理时间限制
    既然是“现存序列中”,也就是说删去时间比它晚的
    那么能产生贡献的数对 ((i,j)) 就要满足 (i < j,val_i > val_j,time_i > time_j)
    这是前面的贡献
    而后面的贡献同理,所以我们在每轮分治中算左区间对右区间的贡献以及右区间对左区间的贡献
    注意:删后还没删完的若干个数我们让它们的删去时间依次递增
    因为没删完的数可以相互贡献,但我们不能重复算同一个数对
    所以我们让时间递增,然后取严格大于来算贡献

    (Code)

    #include<cstdio>
    #include<algorithm>
    #define LL long long
    using namespace std;
    
    const int N = 1e5 + 5;
    int n , m , rd[N] , ans[N] , c[N] , up;
    
    struct node{
    	int a , b , id;
    }f[N];
    
    inline bool cmp(node x , node y){return x.a > y.a;}
    inline int lowbit(int x){return x & (-x);}
    inline void add(int x , int v){for(; x <= up; x += lowbit(x)) c[x] += v;}
    inline int query(int x)
    {
    	int res = 0;
    	for(; x; x -= lowbit(x)) res += c[x];
    	return res;
    }
    
    inline void solve(int l , int r)
    {
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	solve(l , mid) , solve(mid + 1 , r);
    	sort(f + l , f + mid + 1 , cmp) , sort(f + mid + 1 , f + r + 1 , cmp);
    	int j = l;
    	for(register int i = mid + 1; i <= r; i++)
    	{
    		while (f[j].a > f[i].a && j <= mid) add(f[j].b , 1) , j++;
    		ans[f[i].id] += query(up) - query(f[i].b);
    	}
    	for(register int i = l; i < j; i++) add(f[i].b , -1);
    	j = r;
    	for(register int i = mid; i >= l; i--)
    	{
    		while (f[j].a < f[i].a && j >= mid + 1) add(f[j].b , 1) , j--;
    		ans[f[i].id] += query(up) - query(f[i].b);
    	}
    	for(register int i = j + 1; i <= r; i++) add(f[i].b , -1);
    }
    
    int main()
    {
    	scanf("%d%d" , &n , &m);
    	for(register int i = 1; i <= n; i++) scanf("%d" , &f[i].a) , rd[f[i].a] = f[i].id = i;
    	int x;
    	for(register int i = 1; i <= m; i++) scanf("%d" , &x) , f[rd[x]].b = i;
    	up = m;
    	for(register int i = 1; i <= n; i++) 
    	if (!f[i].b) f[i].b = ++up; else rd[f[i].b] = i;
    	solve(1 , n);
    	LL res = 0;
    	for(register int i = 1; i <= n; i++) res += (LL)ans[i];
    	for(register int i = 1; i <= m; i++) printf("%lld
    " , res) , res -= (LL)ans[rd[i]];
    }
    
  • 相关阅读:
    Module not found: Error: Can't resolve './style':配置 extensions 的坑
    Mysql5.7前后修改用户密码变化
    一步步分析Java深拷贝的两种方式clone和序列化
    Windows下Nodejs的开发环境搭建
    JavaNIO第一话Buffer
    Vscode浏览器打开html vscode修改默认浏览器
    Windows电脑多个SSH Key管理.md
    jsonp跨域的原理
    POJ1502(MPI Maelstrom)
    POJ1088(滑雪)
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13492928.html
Copyright © 2020-2023  润新知