3928. 【NOIP2014模拟11.6】射击

Description

有问题,找副连,无聊的时候当然也可以找他啦。小W找到了他的叔叔——东厂厂长——宇宙超级无敌老WS yy。他们叔侄两个商量之后决定用弹弓打破社区里的一些窗户,但是弹弓每秒只能彻底打破一扇窗户。而且如果某户窗户的主人回来了的话,他们就不能进行破坏了(不然会死得很惨的)。因为有的人装的玻璃好,有的人装的玻璃差,有的人装的玻璃高,有的人装的玻璃矮,所以你不能要求他们叔侄两个打破不同的窗户获得的快乐值必须相同。现在他们想知道在能活着的情况下能够获得的最大快乐值。

Input

第一行一个正整数n,表示共有n个窗户。
接下来n行,每行两个整数,第一个为窗子的主人回来的时刻(秒),第二个为破坏该窗户所能获得的快乐值。

Output

最大的快乐值。

Sample Input

4
1 19
2 10
1 20
2 15

Sample Output

35
样例说明:
在第0个时刻,他们选择破坏掉3号窗户,在第1个时刻,因为1号窗户的主人已经回来了,所以不能去破坏1号窗户,只能去破坏2号窗户或4号窗户,显然选择4号窗户。总的快乐值就是20+15=35。

Data Constraint

20%的数据,n<=100。
40%的数据,n<=50000。
100%的数据,n<=200000,快乐值的绝对值不超过32767,时刻非负且小于2^31。

Solution

cur 一个 curcur破就可以了

并查集

首先我们可以发现只有在n以内的时间才是有用的。

那么我们可以按照快乐值降序排列,然后我们相当于用比t[i]小的第一个没有用过的时间来打这个玻璃,如果t[i]以内的时间都用过了(用来打比当前快乐值更大的玻璃了),那么我们就不打这个玻璃,本来这个可以用一个bz表示当前这个时间是否用过,但这样太慢了,于是我们就用并查集来维护,首先我们将所有n以内的时间的父亲赋给它自己,然后每次getfather完之后再将它的父亲赋值成它-1就可以了。

Code1

#include<cstdio>
#include<algorithm>
using namespace std;
int n,i,f[200001],z;
long long ans;
struct node{
	int x,y;
}a[200001];
void up(int x){
	while (f[x]<f[x/2] && x>1){
		int t=f[x/2];
		f[x/2]=f[x];
		f[x]=t;
		x/=2;
	}
}
void down(int x){
	int t;
	while (2*x<=z&&f[x]>=f[2*x] || 2*x+1<=z&&f[x]>=f[2*x+1]){
		int y=2*x;
        if (y+1<=z&&f[y+1]<f[y]) y++;
        t=f[x];
        f[x]=f[y];
        f[y]=t;
        x=y;
	}
}
void kp(int l,int r){
	int i=l,j=r,mid=a[l+rand()%(r-l)].x,t;
	do{
		while(a[i].x<mid) i++;
		while (a[j].x>mid) j--;
		if (i<=j){
			t=a[i].x;
			a[i].x=a[j].x;
			a[j].x=t;
			t=a[i].y;
			a[i].y=a[j].y;
			a[j].y=t;
			i++;
			j--;
		}
	}while (i<=j);
	if (i<r) kp(i,r);
	if (l<j) kp(l,j);
}
int main(){
	scanf("%d",&n);
	for (i=1;i<=n;i++){
		scanf("%lld%lld",&a[i].x,&a[i].y);
		if (a[i].x>n) a[i].x=n;
	}
	kp(1,n);
	for(i=1;i<=n;i++)if(a[i].y>0){
		if(z<a[i].x){
			f[++z]=a[i].y;
			up(z);
		}else{
			if(a[i].y>f[1]){
				f[1]=a[i].y;
				down(1);
			}
		}
	}
	for (i=1;i<=z;i++) ans+=f[i];
	printf("%lld",ans);
}

Code2

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define N 200010
#define ll long long
using namespace std;
ll n,x,y,a[N][2],f[N],ans=0,tot=0;
int cmp(const void *a,const void *b){
	if(((ll*)b)[1]-((ll*)a)[1]!=0) return ((ll*)b)[1]-((ll*)a)[1];
	else return ((ll*)a)[0]-((ll*)b)[0];
}
int get(int x){return f[x]==x?x:f[x]=get(f[x]);}
int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) f[i]=i;
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&x,&y);
		if(y>0) a[++tot][0]=min(x,n),a[tot][1]=y;
	}
	qsort(a+1,tot,sizeof(ll)*2,cmp);
	for(int i=1;i<=tot;i++){
		int fx=get(a[i][0]);
		f[fx]=get(fx-1);
		if(fx) ans+=a[i][1];
	}
	printf("%lld\n",ans);
	return 0;
}


作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/81983179

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/81983179