[NOI Online #1 提高组]冒泡排序
这个题很绕,记数字i前面有cns[i]个数字比他大,逆序对个数就是sigmi cns[i]
反转k次就是让cns[i] - k (i>=1 && i <= n) 而且cns[i]不能有负数
利用两个线段树维护一下,就是有点绕。。。。
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll ;
const int maxn = 2e5+11;
struct Node{
ll ans,sum;
}tree[4][maxn*4];
int update(int id,int node,int be,int en,int i,int val){
int mid = be + en >> 1;
int l = node*2;
int r = node*2+1;
if(be == en){
tree[id][node].ans += val;
if(val > 0) tree[id][node].sum += 1;
if(val < 0) tree[id][node].sum -= 1;
return 0;
}
if(i <= mid) update(id,l,be,mid,i,val);
else update(id,r,mid+1,en,i,val);
tree[id][node].ans = tree[id][l].ans + tree[id][r].ans;
tree[id][node].sum = tree[id][l].sum + tree[id][r].sum;
return 0;
}
ll ask(int id,int node,int be,int en,int LL,int RR){
int mid = be + en >> 1;
int l = node*2;
int r = node*2+1;
if(LL <= be && en <= RR){
return tree[id][node].ans;
}
ll a = 0;
if(LL <= mid) a += ask(id,l,be,mid,LL,RR);
if(RR > mid) a += ask(id,r,mid+1,en,LL,RR);
return a;
}
ll ask2(int id,int node,int be,int en,int LL,int RR){
int mid = be + en >> 1;
int l = node*2;
int r = node*2+1;
if(LL <= be && en <= RR){
return tree[id][node].sum;
}
ll a = 0;
if(LL <= mid) a += ask2(id,l,be,mid,LL,RR);
if(RR > mid) a += ask2(id,r,mid+1,en,LL,RR);
return a;
}
int list[maxn];
ll cns[maxn];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&list[i]);
ll a = 0;
if(list[i] != n) a = ask(0,1,1,n,list[i]+1,n);
cns[list[i]] = a;
update(2,1,1,n,list[i],a);
if(a != 0) update(1,1,1,n,a,a);
update(0,1,1,n,list[i],1);
}
while(m--){
int x,y;
scanf("%d%d",&x,&y);
if(x == 1){
if(list[y] < list[y+1]){
ll ans = cns[list[y]];
if(ans != 0) update(1,1,1,n,ans,-ans);
update(1,1,1,n,ans+1,ans+1);
cns[list[y]]++;
update(2,1,1,n,list[y],1);
}
else{
ll ans = cns[list[y+1]];
update(1,1,1,n,ans,-ans);
if(ans - 1 != 0) update(1,1,1,n,ans-1,ans-1);
cns[list[y+1]]--;
update(2,1,1,n,list[y+1],-1);
}
swap(list[y],list[y+1]);
}
else{
ll ans = 0;
if(y == 0){
ans = ask(2,1,1,n,1,n);
}
else if(y >= n){
ans = 0;
}
else{
ans = ask(2,1,1,n,1,n) - ask(1,1,1,n,1,y) - ask2(1,1,1,n,y+1,n)*y;
// cout<<ask(2,1,1,n,1,n)<<" "<<ask(1,1,1,n,1,y)<<" "<<ask2(1,1,1,n,y+1,n)<<endl;
}
printf("%lld\n",ans);
}
}
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号