社区讨论
逆序对线段树写法求助,悬赏关注两个
学术版参与者 3已保存回复 10
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 10 条
- 当前快照
- 1 份
- 快照标识符
- @lo1y4vjf
- 此快照首次捕获于
- 2023/10/23 04:53 2 年前
- 此快照最后确认于
- 2023/11/03 05:19 2 年前
题目:
描述
给定序列 ,求所有后缀的逆序对个数。即对每个 ,求有多少对 满足 且 。
输入
第一行是正整数。保证 。
第二行
个互不相同的正整数,表示
。保证
。
输出
空格隔开的
个整数,表示
时的答案。
样例
输入
CPP6
5 4 2 6 3 1
输出
CPP0 1 3 4 7 11
我的代码
CPP#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e6;
struct node{
ll sum;
ll tag;
}tree[maxn<<2];
ll arr[maxn+5];
void pushUp(ll root){
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
}
void pushDown(ll root,ll ln,ll rn){
if(tree[root].tag){//Has tag
tree[root<<1].sum+=ln*tree[root].tag;
tree[root<<1|1].sum+=rn*tree[root].tag;
tree[root].tag=0;
}
return ;
}
void build(ll l,ll r,ll root){
if(l==r){
tree[root].sum=arr[l];
return ;
}
ll mid=(l+r)>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushUp(root);
return ;
}
void updateQ(ll l,ll r,ll L,ll R,ll v,ll root){//区间更新
if(L<=l && r<=R){
tree[root].sum+=(r-l+1)*v;
return ;
}
ll mid=(l+r)>>1;
ll ln=mid-l+1,rn=r-mid;
pushDown(root,ln,rn);
if(L<=mid){
updateQ(l,mid,L,R,v,root<<1);
}
if(R>mid){
updateQ(mid+1,r,L,R,v,root<<1|1);
}
pushUp(root);//update
return ;
}
ll query(int l,int r,int L,int R,int root){
ll sum=0;
if(L<=l && r<=R){
return tree[root].sum;
}
ll mid=(l+r)>>1;
ll ln=mid-l+1;
ll rn=r-mid;
if(L<=mid){
sum+=query(l,mid,L,R,root<<1);
}
if(mid<R){
sum+=query(mid+1,r,L,R,root<<1|1);
}
return sum;
}
int main(){
ll n,m;
cin>>n;
int t=0,l,r,v;
int ans=0;
for(int i=1;i<=n;i++){
cin>>t;
ans+=query(1,n,t+1,n,1);
updateQ(1,n,t,t,1,1);
printf("%d ",ans);
}
}
我的代码在当前样例下的输出是
CPP0 1 3 3 6 11
仅能保证最终的逆序对个数正确,不知道为什么
回复
共 10 条回复,欢迎继续交流。
正在加载回复...