首页 > 其他分享 >【题解】CF1830E Bully Sort

【题解】CF1830E Bully Sort

时间:2023-09-10 21:55:41浏览次数:49  
标签:Sort val NN int 题解 mid -- ans CF1830E

考虑一次交换,我们发现,被选出来的 \([i,j]\) 的区间里 \(p_i\) 一定是最大的,\(p_j\) 一定是最小的。

然后我们会发现,我们原序列的逆序对数量会减少 \(2(j-i) - 1\),而 \(\sum|p_i-i|\) 会减少 \(2(j-i)\)

那么答案就是原序列的两部分相减(神奇的性质又增加了!)。

至于我们的后半部分显然是很好维护的,而逆序对数量只需要使用三位偏序求解即可。

yes,搞定!

code:

#include<bits/stdc++.h>
using namespace std;
const int NN = 5e5 + 8;
typedef long long ll;
int n,m,tot;
int p[NN];
ll res[NN];
ll ans[NN];
struct Node{
	int t,x,y,val;
	bool operator < (const Node &A){
		return x < A.x;
	}
}q[NN << 1],Q[NN << 1];
int a[NN];
inline lowbit(int x){return x & (-x);}
void add(int x,int num){
	while(x <= n){
		a[x] += num;
		x += lowbit(x);
	}
}
int ask(int x){
	int res = 0;
	while(x > 0){
		res += a[x];
		x -= lowbit(x);
	}
	return res;
}
void solve(int l,int r){
	if(l == r) return;
	int mid = (l + r) / 2;
	solve(l,mid);solve(mid+1,r);
	
	int i = l,j = mid + 1,k = l;
	while(i <= mid && j <= r){
		if(q[i].x <= q[j].x) add(q[i].y,q[i].val),Q[k++] = q[i++];
        else ans[q[j].t] += (ask(n) - ask(q[j].y)) * q[j].val,Q[k++] = q[j++];
	}
	while(i <= mid) add(q[i].y,q[i].val),Q[k++] = q[i++];
	while(j <= r) ans[q[j].t] += (ask(n) - ask(q[j].y)) * q[j].val,Q[k++] = q[j++];
	for(int i = l; i <= mid; ++i) add(q[i].y,-q[i].val);
	
	i = mid,j = r;
	while(i >= l && j > mid){
		if(q[i].x >= q[j].x) add(q[i].y,q[i].val),--i;
        else ans[q[j].t] += ask(q[j].y-1) * q[j].val,--j;
	}
	while(i >= l) add(q[i].y,q[i].val),--i;
	while(j > mid) ans[q[j].t] += ask(q[j].y-1) * q[j].val,--j;
	for(int i = l; i <= mid; ++i) add(q[i].y,-q[i].val);
	
	for(int i = l; i <= r; ++i) q[i] = Q[i];
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; ++i){
		scanf("%d",&p[i]);
		q[++tot] = {0,i,p[i],1};
		res[0] += abs(p[i] - i);
	}
	for(int i = 1,x,y; i <= m; ++i){
		scanf("%d%d",&x,&y);
		res[i] = res[i-1];
		res[i] -= abs(p[x]-x) + abs(p[y]-y);
		q[++tot] = {i,x,p[x],-1}, q[++tot] = {i,y,p[y],-1};
        swap(p[x],p[y]);
        res[i] += abs(p[x]-x) + abs(p[y]-y);
        q[++tot]={i,x,p[x],1},q[++tot]={i,y,p[y],1};
	}
	solve(1,tot);
	for(int i = 1; i <= m; ++i){
        ans[i] += ans[i-1];
        printf("%lld\n",res[i] - ans[i]);
    }
}

标签:Sort,val,NN,int,题解,mid,--,ans,CF1830E
From: https://www.cnblogs.com/rickylin/p/17692073.html

相关文章

  • CF题解合集
    CF比赛题解合集\(\downarrow2023.09.04\)CF1952,CF19541952A.Ntarsis'Set有一个集合,初始状态里面有数字\(1\)、\(2\)、\(3\)、\(4\)、\(5\)、......、\(10^{1000}\)。现在给你一个长度为\(n\)数组\(a(1\leqa_i\leq10^9)\),要进行\(k\)次操作,每次操作将当前......
  • 【题解】CF1830B The BOSS Can Count Pairs
    你考虑,我们观察数据范围,发现可以是\(O(n\sqrtn)/O(n\logn)\)的,我们又看到乘法,便有几个大概的想法:数论分块\(O(\sqrtn)\)枚举其中一个乘数还有什么……(笔者学识浅陋,读者可以帮忙补充)我们可以找到两种\(O(n^2)\)做法:\(O(n^2)\)枚举数对\((i,j)\)然后进行判断。......
  • 【题解】[ABC318F] Octopus(思维)
    【题解】[ABC318F]Octopus题目链接F-Octopus题意概述有个机器人,它有\(n\)个手臂,第\(i\)个手臂长度为\(l_i\)。同时有\(n\)个宝藏,第\(i\)个宝藏的坐标是\(x_i\)。当机器人位于\(k\)时,它的第\(i\)条手臂可以够到\([k-l_i,k+l_i]\)范围内的宝藏。机器人的每......
  • [ABC319D] Minimum Width 题解
    [ABC319D]MinimumWidth题解题意分析  给定\(n\)个单词,现在想像“记事本”一样把它们依次地一行一行显示出来。每个字母宽度为一,单词之间需要有空格,宽度也为一。一个单词不可以成两部分显示在两行。如果单词最后一个字母来到行末,直接换行,不用空格。  给定窗口最大高度......
  • [JOISC 2016] 雇佣计划 题解
    [JOISC2016]雇佣计划题解这里补充一篇自己的\(n\logn\)做法。本蒟蒻打了两棵线段树,并且进行了繁琐的分类讨论,完全被标算的树状数组吊打qwq题意:给定一个序列\(a\),有两种操作:将\(c\)位置权值改为\(d\);给定一个权值\(b\),定义集合\(S=\{i|a_i\geb\}\),对于......
  • P8029 [COCI2021-2022#3] Akcija 题解
    注:这篇题解中涉及到的所有概念均会在其第一次出现时用斜体标出,有些概念给出了定义,而有些概念的含义请自行意会。定义状态为选了的物品数\(a\)与相应总价格\(b\)的二元组\((a,b)\)。相应地定义状态之间的大小关系、最优状态与状态和状态的加法运算\((a_1,b_1)+(a_2,b......
  • UVA1030 题解
    思路分析猜想我们可以在题目中看出一下几个突破口:能“看穿”的位置所对应的单位立方体是一定不存在的。如果前视图的右上角的颜色\(A\)和顶视图的的右下角颜色\(B\)不同,那么对应的格子就一定不存在。在删除这个立方体后,我们还可以发现,挖去立方体的左侧和\(B\)左侧的......
  • CF431B 题解
    思路分析答题思路一道纯暴力题!因为我们发现数据最大是\(5\),而枚举全排列的时间复杂度为\(\mathcalO(n!)\),对于这种极小的数据范围是丝毫不用顾虑的,因为我们只需要执行\(120\)次。如何快速求出一个数组的全排列?我们可以使用dfs,一层一层获取这个数组的全排列。但是STL......
  • CF387B 题解
    思路分析因为最终要使得\(a,b\)相同,所以我们应该希望让相同的数字尽量相同。所以,我们需要先对\(a\)和\(b\)进行排序,这样子就可以使用双指针的方法来维护最终值了。我们定义\(l\)指针指向\(a_l\),\(r\)指针指向\(b_r\)。因为题目要求添加数字的次数最少,所以我们希望尽......
  • P9516 题解
    思路分析一道很有洛谷个性的模拟签到题。按照题意,我们只需读入\(a,b,c,d,e\),然后对其进行求和,然后依次根据洛谷咕值系统介绍进行判断即可。这样是不是太没有意思了?今天为大家带来一点干货作为福利!介绍:accumulate()函数!简略分析:这个函数可以求出一段区间内的数字之和。S......