【BZOJ3192】【JLOI2013】删除物品 模拟

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/43064295");
}


题解:

代码中init是当前左堆堆顶序号,

然后给每个物品映射排序,暴力从最大一直扫到最小,

每次加上两个序号之间还存在的物品数量(用个树状数组、线段树神马的),然后删除物品修改init……


反正水到爆,乱搞就好。


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 101000
using namespace std;
struct LSH
{
	int x,id;
	bool operator < (const LSH &a)const{return x<a.x;}
	LSH(int _x=0,int _id=0):x(_x),id(_id){}
}seq[N];
int n,m,init;

int fw[N];
inline void add(int x,int w){for(;x<=n;x+=(x&-x))fw[x]+=w;}
inline int query(int x){int ans=0;for(;x;x-=(x&-x))ans+=fw[x];return ans;}

int main()
{
	int i,j,k;
	int a,b,c;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a);
		seq[i]=LSH(-a,n-i+1);
	}
	init=n;
	for(i=1;i<=m;i++)
	{
		scanf("%d",&a);
		seq[i+n]=LSH(-a,i+n);
	}
	n+=m;
	sort(seq+1,seq+n+1);
	// 输入完毕
	// init 初始指针,默认为两点中的左端点
	for(i=1;i<=n;i++)add(i,1);

	long long ans=0;
	for(i=1;i<=n;i++)
	{
		int d=seq[i].id;
		if(init<=d)
		{
			int t=query(d-1)-query(init);
			if(t>0)ans+=t;
			add(d,-1),init=d;
		}
		else {
			int t=query(init)-query(d);
			if(t>0)ans+=t;
			add(d,-1),init=d;
		}
	}
	cout<<ans<<endl;
	return 0;
}


你可能感兴趣的:(模拟,JLOI2013,BZOJ3192,删除物品)