• bzoj3295: [Cqoi2011]动态逆序对


    题目链接

    bzoj3295: [Cqoi2011]动态逆序对

    题解

    好神呐,删除转化为插入,然后得到了插入的时间关系
    然后问题就转化成了三维偏序问题

    代码

    #include <iostream>
    #include <cstdio>
    // n * (2 * n + 1) + 1; 
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int N=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m;
    int pos[N];
    struct Q{
        int t,x,y; 
        Q(int t,int id,int v):t(t),x(id),y(v){}
        bool operator < (const Q & A)const{
            return x == A.x ? y < A.y : x < A.x; 
        } 
    }q[N],t[N]; 
    inline bool cmp(const Q &q,const Q &b) {   
      	return q.t == b.t ? q.x<b.x : q.t<b.t;
    }
    int c[N];  
    namespace BIT {
    #define lowbit(x) (x & -x)	
    	int sum[maxn]; 
    	void add(int idx,int val) {
    		for(;idx <= n;idx += lowbit(idx)) sum[idx] += val; 	 
    	} 
    	int query(int idx) { 
    		int ret = 0;for(;idx;idx -= lowbit(idx)) ret += sum[idx]; 
    		return ret;  
    	} 
     	
    }  
    LL ans[N];  
    void cdq(int l,int r) {  
        if(l == r) return; 
        int mid = (l + r) >> 1; 
        cdq(l,mid); cdq(mid + 1,r); 
        int i = l,j = mid + 1,p = l; 
        while(i <= mid && j <= r) {  
            if(q[i] < q[j]) BIT::add(q[i].y,1),t[p ++] = q[i ++];  
            else ans[q[j].t] += BIT::query(n) - (q[j].y) , t[p++] = q[j ++]; 
        } 
        for(int i = l;i <= mid;i ++) add(q[i].y,- 1); 
        for(int i = l;i <= r;i ++) q[i] = t[i]; 
        for(int i = r;i >= l;i --) { 
            if(q[i].t <= mid) add(q[i].y,1); 
            else ans[q[i].t] += sum(q[i].y); 
        } 
        for(int i=l;i<=r;i++) if(q[i].t<=mid) add(q[i].y,-1);
    }
    int main() { 
        n = read(); m = read();
        for(int i = 1;i <= n ;i ++) q[i] = Q(0,i,read()) , pos[q[i].y] = i;
        int Tim = n; 
        for(int i = 1;i <= m;i ++) q[pos[read()]].t = Tim --;  
        for(int i = 1;i <= n;i ++) if(!q[i].t) q[i].t = Tim --;  
    	sort(q + 1,q + 1 + n,cmp); 
        cdq(1,n);  
        for(int i=1;i<=n;i++) ans[i]+=ans[i-1]; 
        for(int i=n;i>=n-m+1;i--) printf("%lld
    ",ans[i]);
    } 
    
  • 相关阅读:
    动态规划(最长公共序列,最长上升序列)
    滴滴笔试--算术转移(20190827)
    线段树和树状数组
    pair和list学习
    数据结构--树(建立、遍历)
    tmux常用命令与快捷键
    机器学习实战-逻辑回归
    字符流中第一个重复的字符
    机器学习实战-朴素贝叶斯
    Python第三方库
  • 原文地址:https://www.cnblogs.com/sssy/p/9260532.html
Copyright © 2020-2023  润新知