• 【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]];
    }
    
  • 相关阅读:
    查看服务器
    AspectJ JoinPoint及ProceedingJoinPoint 简要api文档
    shrio的springboot完整配置
    shiro配置springboot的基本配置
    shiro的ssm集成和简单的开发尝试
    编写高质量的Python代码系列(八)之部署
    编写高质量的Python代码系列(七)之协作开发
    编写高质量的Python代码系列(六)之内置模块
    编写高质量的Python代码系列(五)之并发与并行
    编写高质量的Python代码系列(四)之元类及属性
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13492928.html
Copyright © 2020-2023  润新知