zoukankan      html  css  js  c++  java
  • 题解 Yuno loves sqrt technology II

    题目传送门

    题目大意

    (n)个数,(m)个查询,每次查询一个区间内的逆序对个数。

    (n,mle 10^5)

    思路

    其实是为了锻炼二次离线才做这道题的。

    不难想到可以有一个(Theta(nsqrt nlog n))的方法,即用莫队,每次用树状数组计算变化的贡献。

    然后我们就可以想到二次离线了。我们考虑计算([l,r] o [l,r^{'}])的贡献,可以发现([l,r] o[l,r+1])变换的贡献就是([l,r])中比(a_{r+1})大的个数,差分一下,就是([1,r])中比(a_{r+1})大的个数减去([1,l-1])中比(a_{r+1})大的个数。我们发现前面那个东西可以(Theta(nlog n))预处理出来,后面那个东西可以再次离线下来用值域分块(Theta(nsqrt n))求出来。

    我们再来考虑([l,r] o [l^{'},r])的变化。([l,r] o [l-1,r])的贡献就是([l,r])中比(a_{l-1})小的个数,差分一下,即是([l,n])中比(a_{l-1})小的个数减去([r+1,n])中比(a_{l-1})小的个数。前面那个东西同样可以离线(Theta(nlog n)),后面那个也可以(Theta(nsqrt n))值域分块。

    于是,我们的总时间复杂度即为(Theta(msqrt n+nsqrt n))

    但是这道题非常卡常。

    ( exttt{Code})

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define ll long long
    #define MAXN 100005
    #define MAXM 355
    
    ll ans[MAXN],sum1[MAXN],sum2[MAXN];
    int n,m,un,tot,siz,h[MAXN],w[MAXN],bel[MAXN],tmp[MAXN],laz[MAXM],col[MAXM],cor[MAXM],tree[MAXN];
    
    struct Query{
    	int l,r,id;
    	bool operator < (const Query &p)const{return (l / siz) != (p.l / siz) ? l < p.l : r < p.r;}
    }q[MAXN];
    
    struct node{int p,l,r,id;};
    vector <node> vec1[MAXN],vec2[MAXN];
    
    void add1 (int i,int p,int l,int r,int id){vec1[i].push_back (node {p,l,r,id});}
    void add2 (int i,int p,int l,int r,int id){vec2[i].push_back (node {p,l,r,id});}
    
    int lowbit (int x){return x & (-x);}
    void update (int x,int k){for (;x <= n;x += lowbit (x)) tree[x] += k;}
    int query (int x){int sum = 0;for (;x;x -= lowbit (x)) sum += tree[x];return sum;}
    
    void pushup1 (int x){
    	if (laz[bel[x]]) for (Int i = col[bel[x]];i <= cor[bel[x]];++ i) w[i] += laz[bel[x]];laz[bel[x]] = 0;
    	for (Int i = col[bel[x]];i <= x;++ i) w[i] ++;
    	for (Int i = 1;i < bel[x];++ i) laz[i] ++;
    }
    
    void pushup2 (int x){
    	if (laz[bel[x]]) for (Int i = col[bel[x]];i <= cor[bel[x]];++ i) w[i] += laz[bel[x]];laz[bel[x]] = 0;
    	for (Int i = x;i <= cor[bel[x]];++ i) w[i] ++;
    	for (Int i = bel[x] + 1;i <= tot;++ i) laz[i] ++;
    }
    
    void solve (){//二次离线部分
    	int cnt = sqrt (un);col[tot = 1] = 1;
    	if (cnt * cnt < un) ++ cnt;
    	for (Int i = 1;i <= un;++ i){
    		bel[i] = tot;
    		if (i % cnt == 0) cor[tot] = i,col[++ tot] = i + 1;
    	}
    	cor[tot] = un;
    	for (Int i = 1;i <= n;++ i){
    		for (Int j = 0,len = vec1[i].size();j < len;++ j){
    			int id = vec1[i][j].id,p = vec1[i][j].p;
    			for (Int k = vec1[i][j].l;k <= vec1[i][j].r;++ k) ans[id] += 1ll * p * (laz[bel[h[k] + 1]] + w[h[k] + 1]);
    		}
    		pushup1 (h[i]);
    	}
    	for (Int i = 1;i <= tot;++ i) laz[i] = 0;
    	for (Int i = 1;i <= un + 1;++ i) w[i] = 0;
    	for (Int i = n;i >= 1;-- i){
    		for (Int j = 0,len =   vec2[i].size();j < len;++ j){
    			int id = vec2[i][j].id,p = vec2[i][j].p;
    			for (Int k = vec2[i][j].l;k <= vec2[i][j].r;++ k) ans[id] += 1ll * p * (laz[bel[h[k] - 1]] + w[h[k] - 1]);
    		}
    		pushup2 (h[i]);
    	}
    }
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    signed main(){
    	read (n,m),siz = 317;
    	for (Int i = 1;i <= n;++ i) read (h[i]),tmp[i] = h[i];
    	sort (tmp + 1,tmp + n + 1);un = unique (tmp + 1,tmp + n + 1) - tmp - 1;
    	for (Int i = 1;i <= n;++ i) h[i] = lower_bound (tmp + 1,tmp + un + 1,h[i]) - tmp;
    	for (Int i = 1;i <= m;++ i) read (q[i].l,q[i].r),q[i].id = i;sort (q + 1,q + m + 1);
    	for (Int i = 1;i <= n;++ i) sum1[i] = sum1[i - 1] + i - 1 - query (h[i]),update (h[i],1);
    	for (Int i = 1;i <= n;++ i) tree[i] = 0;
    	for (Int i = n;i;-- i) sum2[i] = sum2[i + 1] + query (h[i] - 1),update (h[i],1);
    	int l = 1,r = 0;
    	for (Int i = 1;i <= m;++ i){
    		if (r < q[i].r) ans[q[i].id] += sum1[q[i].r] - sum1[r],add1 (l,-1,r + 1,q[i].r,q[i].id),r = q[i].r;
    		if (r > q[i].r) ans[q[i].id] -= sum1[r] - sum1[q[i].r],add1 (l,1,q[i].r + 1,r,q[i].id),r = q[i].r;
    		if (l < q[i].l) ans[q[i].id] -= sum2[l] - sum2[q[i].l],add2 (r,1,l,q[i].l - 1,q[i].id),l = q[i].l;
    		if (l > q[i].l) ans[q[i].id] += sum2[q[i].l] - sum2[l],add2 (r,-1,q[i].l,l - 1,q[i].id),l = q[i].l;
    	}
    	solve ();
    	for (Int i = 1;i <= m;++ i) ans[q[i].id] += ans[q[i - 1].id];
    	for (Int i = 1;i <= m;++ i) write (ans[i]),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    WPF 快捷键读写txt
    win10 UWP GET Post
    win10 UWP GET Post
    win10 UWP Hmac
    win10 UWP Hmac
    win10 UWP MessageDialog 和 ContentDialog
    MySQL 触发器-更新字段时,status列会加一
    [SDOI2018]旧试题
    win10 UWP MessageDialog 和 ContentDialog
    win10 UWP RSS阅读器
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13370157.html
Copyright © 2011-2022 走看看