• CodeForces 785E Anton and Permutation 分块


    题意:

    有一个(1 sim n)的排列(A),有(q)个询问:
    交换任意两个元素的位置,求交换之后排列的逆序数

    分析:

    像这种不太容易用线段树,树状数组维护的可以考虑分块
    (sqrt{n})个元素划分为一块,然后两端的块可以直接扫出逆序数的变化,中间的块可以用二分计算逆序数
    在更新块的时候,可以二分查找要插入或删除的位置
    每次询问的复杂度为(O(sqrt{n}logsqrt{n})=O(sqrt{n}logn))

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 200000 + 10;
    const int maxsqrt = 500;
    
    #define ALL(x) x.begin(), x.end()
    
    int n, q, a[maxn];
    int st[maxsqrt], ed[maxsqrt];
    vector<int> b[maxsqrt];
    
    int main()
    {
    	scanf("%d%d", &n, &q);
    	int col = (int)sqrt(n);
    	for(int i = 0; i < n / col; i++) { st[i] = col * i; ed[i] = col * (i + 1); }
    	if(n % col > 0) { st[n / col] = n - (n % col); ed[n / col] = n; }
    
    	for(int i = 0; i < n; i++) {
    		a[i] = i;
    		b[i / col].push_back(i);
    	}
    
    	long long ans = 0;
    	while(q--) {
    		int l, r; scanf("%d%d", &l, &r);
    		l--; r--;
    		if(l == r) { printf("%lld
    ", ans); continue; }
    		if(l > r) swap(l, r);
    		int idl = l / col, idr = r / col;
    
    		//update
    		for(int i = idl + 1; i < idr; i++) {
    			int size = b[i].size();
    			int p = lower_bound(ALL(b[i]), a[l]) - b[i].begin();
    			ans -= p;
    			ans += size - p;
    			p = lower_bound(ALL(b[i]), a[r]) - b[i].begin();
    			ans += p;
    			ans -= size - p;
    		}
    
    		for(int i = l + 1; i < ed[idl] && i < r; i++) {
    			if(a[i] > a[l]) ans++; else ans--;
    			if(a[i] > a[r]) ans--; else ans++;
    		}
    		for(int i = st[idr]; i < r && i > l; i++) {
    			if(a[i] > a[l]) ans++; else ans--;
    			if(a[i] > a[r]) ans--; else ans++;
    		}
    		
    		//swap
    		if(idl < idr) {
    			b[idl].erase(lower_bound(ALL(b[idl]), a[l]));
    			b[idl].insert(lower_bound(ALL(b[idl]), a[r]), a[r]);
    			b[idr].erase(lower_bound(ALL(b[idr]), a[r]));
    			b[idr].insert(lower_bound(ALL(b[idr]), a[l]), a[l]);
    		}
    		if(a[l] < a[r]) ans++; else ans--;
    		swap(a[l], a[r]);
    
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    linux 文件时间
    linux命令学习 touch
    linux命令学习 cp
    Linux命令学习 mv
    SpringMVC mvc详解
    JDBC原生态代码
    java中静态方法中调用非静态方法的详解
    Spring技术详解
    Spring中的 BeanFactory和 ApplicationContext的区别与解释
    java多线程编程相关技术
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/6574589.html
Copyright © 2020-2023  润新知