MnZn求助动态开点线段树
查看原帖
MnZn求助动态开点线段树
229373
Xeqwq楼主2022/4/27 20:46

rt.好像没必要动态开点 但是来练练手
样例会卡死

#include <iostream>
using namespace std;
typedef long long ll;
const int Maxn=3e4+5,Maxa=1e5+5;
int n,a[Maxn],num=1;
struct Segt
{
	int l,r,dat;
}t[Maxn<<6];
void build()
{
	t[1].l=0;
	t[1].r=Maxa;
}
void clear()
{
	for(int i=1;i<=(Maxn<<6);i++) t[i].dat=t[i].l=t[i].r=0;
}
void pushup(int p)
{
	t[p].dat=t[t[p].l].dat+t[t[p].r].dat;
}
void modify(int p,int l,int r,int x)
{
	if(l==r) t[p].dat++;
	int mid=(l+r)>>1;
	if(!t[p].l) t[p].l=++num;
	if(!t[p].r) t[p].r=++num;
	if(x<=mid) modify(t[p].l,l,mid,x);
	else modify(t[p].r,mid+1,r,x);
	pushup(p); 
}
int query(int p,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr) return t[p].dat;
	int mid=(l+r)>>1,ret=0;
	if(ql<=mid&&t[p].l) ret+=query(t[p].l,l,mid,ql,qr);
	if(mid<qr&&t[p].r) ret+=query(t[p].r,mid+1,r,ql,qr);
	return ret;
}
int bigger[Maxn],smaller[Maxn];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build();
	for(int i=1;i<=n;i++)
	{
		modify(1,0,Maxa,a[i]);
		if(a[i]) smaller[i]=query(1,0,Maxa,0,a[i]-1);
	}
	clear(); 
	build();
	for(int i=n;i>=1;i--)
	{
		modify(1,0,Maxa,a[i]);
		bigger[i]=query(1,0,Maxa,a[i]+1,Maxa);
	}
	ll ans=0;
	for(int i=2;i<n;i++) ans+=bigger[i]+smaller[i];
}
2022/4/27 20:46
加载中...