CQOI2011动态逆序对--cdq分治

题意:给出一个1~n的排列,按顺序删掉m个元素,求出每次删除操作之前序列的逆序对个数.

做法:这题显然可以用树套树之类的工业结构维护,但是我怎么可能会呢.

考虑离线cdq分治,可以把问题反过来,转化为每次添加一个元素,求添加后序列的逆序对个数.

把每个元素看成平面上的点,x,y坐标分别是元素大小和插入位置,产生贡献的一对点则满足(x

设f[i]是添加第i个元素后,包含i的逆序对个数,那么只有之前添加的点对它产生影响,x维排序,y维用树状数组维护,然后x,y交换再做一遍就好了.

PS:之前排序用的sort,就T了,简直太迷了.

#include
#include
#include
#include
using namespace std;
#define REP(I,ST,ED) for(int I=ST,I##end=ED;I<=I##end;++I)
#define DREP(I,ST,ED) for(int I=ST,I##end=ED;I>=I##end;--I)
typedef long long ll;
namespace ioput{
	int read(){
		int x=0;
		char c=getchar();
		while((c<'0')||(c>'9'))c=getchar();
		while((c>='0')&&(c<='9'))x=x*10+c-'0',c=getchar();
		return x;
	}
	char t[20];
	int tlen;
	void write(ll x){
		t[tlen=0]='\n';
		if(x==0)t[++tlen]=0;
		while(x)
			t[++tlen]=x%10+'0',x/=10;
		DREP(i,tlen,0)putchar(t[i]);
	}
}
using namespace ioput;
const int maxn=100005;
struct node{int x,y,id;}a[maxn],b[maxn],ta[maxn];
int n,m,tot,pos[maxn];
bool vis[maxn];
ll ans[maxn];
namespace Binary_Indexed_Tree{
	ll c[maxn];
	void add(int x,int val){
		while(x<=n)
			c[x]+=val,x+=x&-x;
	}
	int query(int x){
		int res=0;
		while(x)
			res+=c[x],x-=x&-x;
		return res;
	}
}
using namespace Binary_Indexed_Tree;
void solve(int l,int r){
	if(l>=r)return;
	int mid=(l+r)>>1,cur=l,curl=l,curr=mid+1;
	solve(l,mid),solve(mid+1,r);
	while((curl<=mid)&&(curr<=r)){
		if(a[curl].x


你可能感兴趣的:(cdq分治)