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;
}


發佈了34 篇原創文章 · 獲贊 1 · 訪問量 9802
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章