• Codeforece E. Anton and Permutation


    主席树算贡献l,r中交换位置,算出>=rank(h) 和 <=rank(h)  a[l],a[r] 先不统计 a[l]比a[r]大的话交换后ans-1,a[l]比a[r]小的话交换后ans-1,ans+<r的,->r的 ans-<l的,+>l的,区间比k大的数量或者区间第k大等类似的可以用第二类主席树弄
    
    #include <cstdio>
    #include <memory>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <vector>
    #include <cassert>
    #include <string>
    #include <ctime>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <iostream>
    #include <cassert>
    #include <set>
    using namespace std;
    #define REP(i,n) for(int i=0;i<n;i++)
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define req(i,a,b) for(int i=a;i>=b;i--)
    #define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
    #define cl(a,b) memset(a,b,sizeof a);
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mod 10007
    const int inf = ~0u >> 2;
    const ll INF = (1LL << 62) - 1;
    double eps = 1e-12;
    const int N = 500005 + 5;
    const int M = 200005;
    
    int n, m, d;
    int a[500005];
    int rnk[N];
    int root[N];
    int croot[N];
    int sz = 0, tot = 0;
    void insert(int &num, int val, int k, int l, int r);
    struct Node {
    	int sum;
    	int ch[2];
    }T[30500010];
    void insert(int &num, int val, int k, int l, int r, int flag) {
    	if (flag == 0 || num == 0) {
    		T[++sz] = T[num]; num = sz;
    	}
    	T[num].sum += val;
    	if (l == r) {
    		return;
    	}
    	int m = (l + r) >> 1;
    	if (k <= m) {
    		insert(T[num].ch[0], val, k, l, m, flag);
    	}
    	else {
    		insert(T[num].ch[1], val, k, m + 1, r, flag);
    	}
    }
    int query(int i, int j, int k, int l, int r) {
    	if (k > T[j].sum - T[i].sum)
    		k = T[i].sum - T[i].sum;
    	if (l == r)
    		return l;
    	int m = (l + r) >> 1;
    	if (k <= T[T[j].ch[0]].sum - T[T[i].ch[0]].sum)
    		return query(T[i].ch[0], T[j].ch[0], k, l, m);
    	else
    		return query(T[i].ch[1], T[j].ch[1], k - (T[T[j].ch[0]].sum - T[T[i].ch[0]].sum), m + 1, r);
    }
    void add(int x, int num, int d) {
    	while (x <= tot) {
    		insert(croot[x], d, num, 1, tot, 1);
    		x += x&-x;
    	}
    }
    struct Pack {
    	vector<int> v;
    	Pack() {}
    	Pack(int x) { v.push_back(x); }
    	void operator +=(int x) {
    		v.push_back(x);
    	}
    	operator ll()const {//得到左孩子和
    		ll ret = 0;
    		for (int i = 0; i<v.size(); i++)
    			ret += T[T[v[i]].ch[0]].sum;
    		return ret;
    	}
    	void lt() {
    		for (int i = 0; i < v.size(); i++)
    			v[i] = T[v[i]].ch[0];
    	}
    	void rt() {
    		for (int i = 0; i < v.size(); i++)
    			v[i] = T[v[i]].ch[1];
    	}
    };
    Pack sum(int x, int k) {
    	Pack ret;
    	while (x>0) {
    		ret += croot[x];
    		x -= x&-x;
    	}
    	return ret;
    }
    ll binSearch(int l, int r, int k) {
    	Pack treesl = sum(l,0);
    	Pack treesr = sum(r,0);
    	Pack presl = Pack(root[l]);
    	Pack presr = Pack(root[r]);
    	int xl = 1, xr = tot;
    	ll ret = 0;
    	int rtl = root[l];
    	int rtr = root[r];
    	while (xl < xr) {
    		int mid = (xl + xr) >> 1;
    		ll t = treesr - treesl + presr - presl;
    		if (mid <= k) {
    			ret += t;
    			treesr.rt(); treesl.rt(); presr.rt(); presl.rt();
    			//ret += T[T[rtr].ch[0]].sum - T[T[rtl].ch[0]].sum;
    			xl = mid+1;
    			if (mid == k) {
    				ret--;
    				break;
    			}
    		}
    		else {
    			treesr.lt(); treesl.lt(); presr.lt(); presl.lt();
    			xr = mid;
    		}
    	}
    	return ret;
    }
    struct Seg {
    	int l, r, h, x;
    }q[M];
    int val[N];
    int cnt = 0;
    int Hash(int x) {
    	return lower_bound(val, val + tot, x) - val + 1;
    }
    int b[N];
    int main() {
    	//for (int i = 0; i <= sz; i++)T[i] = T[0];
    	cnt = 0;
    	sz = 0;
    	tot = 0;
    
    	scanf("%d%d", &n, &m);
    
    	for (int i = 1; i <= n; i++) {
    		a[i] = i;
    		b[i] = i;
    		val[cnt++] = a[i];
    	}
    	for (int i = 0; i < m; i++) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		if (x > y)
    			swap(x, y);
    		q[i * 4].l = x;
    		q[i * 4].r = y;
    		q[i * 4].h = b[y];
    		q[i * 4].x = -1;
    		q[i * 4 + 1].l = x;
    		q[i * 4 + 1].r = y;
    		q[i * 4 + 1].h = b[x];
    		q[i * 4 + 1].x = -2;
    		
    		q[i*4+2].x = x;
    		q[i*4+2].h = b[y];
    		//val[cnt++] = b[y];
    		q[i*4+2].l = -inf;
    		q[i * 4+3].x = y;
    		q[i * 4+3].h = b[x];
    		//val[cnt++] = b[x];
    		q[i * 4+3].l = -inf;
    		
    		swap(b[x], b[y]);
    			/*if (l<1 || r>n || l>r || h<1 || h>r - l + 1)
    				assert(false);*/
    	}
    	sort(val, val + cnt);
    	rnk[0] = ++tot;
    	for (int i = 1; i < cnt; i++) {
    		if (val[i] != val[i - 1])
    			rnk[i] = ++tot;
    		else
    			rnk[i] = tot;
    	}
    	for (int i = 0; i <= tot; i++)croot[i] = 0;
    	unique(val, val + cnt);
    	root[0] = 0;
    	for (int i = 1; i <= n; i++) {
    		root[i] = root[i - 1];
    		insert(root[i], 1, Hash(a[i]), 1, tot, 0);
    	}
    	ll ans = 0;
    	for (int i = 0; i < 4*m; i++) {
    		if (q[i].l != -inf) {
    			if (q[i].x == -1) {
    				if (q[i].l != q[i].r) {
    					ll tmp = binSearch(q[i].l - 1, q[i].r, Hash(q[i].h));
    					if (a[q[i].l] < a[q[i].r])
    						tmp--;
    					ans += tmp;
    					ans -= max(0LL, (q[i].r - q[i].l - tmp - 1));
    				}
    				//printf("%d
    ", val[binSearch(q[i].l - 1, q[i].r, q[i].h) - 1]);
    			}
    			if (q[i].x == -2) {
    				if (q[i].l != q[i].r) {
    					ll tmp = binSearch(q[i].l - 1, q[i].r, Hash(q[i].h));
    					if (a[q[i].l] > a[q[i].r])
    						tmp--;
    					ans -= tmp;
    					ans += max(0LL, (q[i].r - q[i].l - tmp - 1));
    				}
    				if (a[q[i].l] > a[q[i].r])
    					ans--;
    				else if(a[q[i].l]<a[q[i].r])
    					ans++;
    				cout << ans << endl;
    			}
    		}
    		else {
    			add(q[i].x, Hash(a[q[i].x]), -1);
    			a[q[i].x] = q[i].h;
    			add(q[i].x, Hash(q[i].h), 1);
    		}
    	}
    	//cout << ans << endl;
    	/*for (int i = 1; i <= tot; i++)
    		croot[i] = 0, val[i] = 0, a[i] = 0;*/
    	
    	return 0;
    }
    
  • 相关阅读:
    Uniprot Accession的格式以及正则表达式
    python正则表达式统计字符串的个数
    apache开启图片缓存压缩
    mysql之备份表和备份数据库
    linux下lampp的启动和停止脚本
    linux下tomcat的启动,停止,重启脚本
    文件上传PHP
    Assembly测试
    List之Sort使用
    Ienumerable和Ienumerator的使用
  • 原文地址:https://www.cnblogs.com/HaibaraAi/p/6561528.html
Copyright © 2020-2023  润新知