zoukankan      html  css  js  c++  java
  • 【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]];
    }
    
  • 相关阅读:
    1全志 A20 camera移植
    MySQL使用日期列作为UNIQUE索引
    MySQL 根据JSON类型的字段进行过滤数据的方式
    MySQL 根据JSON类型的字段进行过滤数据的方式
    DateUtils互转工具类
    URL转义特定字符
    POI Excel索引是从0还是1开始??
    百度地图Api使用常见问题
    SpringBoot项目意外出现 循环依赖和注入的对象意外是Null的问题 Requested bean is currently in creation: Is there an unresolvable circular reference? 或 nested exception is java.lang.NullPointerException
    MybatisPlus 多租户的常见问题
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13492928.html
Copyright © 2011-2022 走看看