theHermit @ 2020-09-26 22:04:30
#include<bits/stdc++.h>
#define For(i,m,n) for(register int i=m;i<n;i++)
#define rFor(i,m,n) for(register int i=m;i>n;i--)
#define r(a) read(a)
#define rr(a,b) read(a),read(b)
#define rrr(a,b,c) read(a),read(b),read(c)
using namespace std;
typedef long long ll;
template <class T>
inline void read(T &x)
{
x=0;
T f=1;
char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
x=x*f;
}
const int MAXN=1000100;
const int INF=214783647;
ll n,m,a[MAXN],ans[MAXN<<2],add_tag[MAXN<<2];
ll sum[MAXN<<2];
ll bucket[MAXN];
ll smaller[MAXN],bigger[MAXN];
ll res=0;
struct state{
ll val;
ll ord;
}in[MAXN];
void show()
{
For(i,0,15){
printf("tree[%d] = %d\n",i,ans[i]);
}
cout<<endl;
}
inline int ls(int x)
{
return x<<1;
}
inline int rs(int x)
{
return x<<1|1;
}
ll query(ll L,ll R,ll lo,ll hi,ll node)
{
if(L<=lo&&hi<=R)return sum[node];//如果这就是我们想要的区间
ll mid=(lo+hi)>>1;
ll res=0;
//res是根据我们父节点相应的规则,取得不同的值
if(L<=mid)res+=query(L,R,lo,mid,ls(node));//这里可能要改
if(R>mid) res+=query(L,R,mid+1,hi,rs(node));
return res;
}
inline void push_up(int node)
{
sum[node]=sum[ls(node)]+sum[rs(node)];
}
void build(int node,int lo,int hi)
{
if(lo==hi){
return;
}//这个是只有输入数据的数组,才会赋值给输入数据的节点层
int mid=(lo+hi)>>1;
build(ls(node),lo,mid);
build(rs(node),mid+1,hi);
push_up(node);//根据题目操作要改,这里是根据输入数据,构建线段树输入数据的爸爸
}
void updateKmax(ll pos,ll lo,ll hi,ll node)
{
if(lo==pos&&hi==pos){
sum[node]++;
return;
}
ll mid=(lo+hi)>>1;
if(pos<=mid) updateKmax(pos,lo,mid,ls(node));
else if(pos>mid) updateKmax(pos,mid+1,hi,rs(node));
push_up(node);
}
bool cmp(state &n1,state &n2)
{
if(n1.val!=n2.val) return n1.val<n2.val;
else return n1.ord<n2.ord;
}
void input()
{
r(n);
For(i,1,n+1){
r(in[i].val);
in[i].ord=i;
}
sort(in+1,in+1+n,cmp);//从小到大排列权值
int cnt=0;
//离散化,重新排列权值
For(i,1,n+1){
if(in[i].val>in[i-1].val) cnt++;
bucket[in[i].ord]=cnt;
}
build(1,1,n);
//求出比当前i大的bigger[i]个数字
rFor(i,n,0){
if(bucket[i]<n) bigger[i]=query(bucket[i]+1,n,1,n,1);
updateKmax(bucket[i],1,n,1);
}
For(i,1,n){
res+=(n-i-bigger[i]);
}
}
int main()
{
input();
cout<<res;
return 0;
}
by theHermit @ 2020-09-26 22:11:45
我明白了!!!!!
最后不能直接res+=(n-i-bigger[i])
因为有重复的数QAQ
我是琪露诺(雾
by theHermit @ 2020-09-26 22:19:53
更改后应为:
For(i,1,n){
int num=--mp[bucket[in[i].ord]];
res+=(n-i-num-bigger[i]);
}