codeforces 882C Hacker, pack your bags!


傳送門

愚蠢的博主又上線啦!

這題博主一看排序+樹狀數組o(n*logn),先分類把天數相同的證件拿一個vector存(拿數組就炸了,vector的話空間就是o(n)了),然后按l第一關鍵字,r第二關鍵字,價值第三關鍵字排序,然后枚舉n個證件,用x減去這個證件的天數,然后在相應的vector內,分兩段l之前和r之后,然后樹狀數組求這兩個區間的最大值。

然后博主非常尷尬wa了一個小時。。

正解是很勁的貪心,掃一遍就行了。。真心想不出來(實際是博主菜)

首先設個數組f[i]表示證件為i天的最大價值,然后分兩個數組排序(一個按l,一個按r),實際是一個為第一個證件一個為第二個證件,因為兩天不想交肯定有第一個的r小於第二個的l,所以先枚舉按l排序的證,件然后枚舉按r排序的證件第一個的r大於第二個的l,所以對於第一個證件肯定滿足提供f[i]的證件與其不相交(因為第一個證件日期后面的還沒掃),注意f[i]當且僅當對當前的第一個證件有用,然后在枚舉第二證件的過程中求出f[i](i=[1,i])的值,然后對於ans更新(就是比較ans和第1個證件與其匹配的證件價值和)

UPDATE(7.19):其實這是一個單調棧以第一個證件枚舉,做單調棧

注意:不存在配對的情況輸出-1。

ps:博主調不對那個愚蠢的排序+線段樹了,那就不調了(就是所謂的打不過就加入(黑一發勇士))。

代碼:

#include<iostream>
#include<stdio.h>
#include<algorithm> 
using namespace std;
const int Maxn=2*100005;
const int oo=2147483647;
struct node
{
	int l,r,v,d; 
}days_A[Maxn],days_B[Maxn];
int f[Maxn];
int cmp_A(node a,node b)
{
	return a.l<b.l;
}
int cmp_B(node a,node b)
{
	return a.r<b.r;
}
int main()
{
	int n,x,ans=oo;
	scanf("%d%d",&n,&x);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&days_A[i].l,&days_A[i].r,&days_A[i].v);
		days_A[i].d=days_A[i].r-days_A[i].l+1;
		days_B[i]=days_A[i];
	}
	for(int i=0;i<=x;i++)
		f[i]=oo;
	sort(days_A+1,days_A+n+1,cmp_A);
	sort(days_B+1,days_B+n+1,cmp_B);
	int j=0;
	for(int i=1;i<=n;i++)
	{
		while(j<=n&&days_A[i].l>days_B[j].r)
		{
			f[days_B[j].d]=min(f[days_B[j].d],days_B[j].v);
			j++;
		}
		if(x-days_A[i].d>0&&f[x-days_A[i].d]!=oo)
			ans=min(ans,f[x-days_A[i].d]+days_A[i].v);
	}
	printf("%d",(ans==oo)?-1:ans);
	return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com