[CERC2016] bzoj 4795 爵士之旅 Jazz Journey - 贪心

题目大意:
转化后是给一个ab序列,四种方案:删a,删b,删一个{a,b}子序列,删一个{b,a}子序列。各有代价。问删光的最小代价。
题解:A=min(A,AB),AB=min(AB,A+B),然后有max(AB,BA)<=A+B。不妨AB<=BA<=A+B,那么先删ab,再删ba,再单删a和b即可。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define N 300010
#define BAS 1000000ll
#define INF INT_MAX
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
vector<pii> vec;unordered_map<lint,lint> es;pii t[N];int d[N],del[N],s[N],a[N];vector<int> lst[N];
inline lint hv(int x,int y,int z) { return x*BAS*BAS+y*BAS+z; }
inline lint E(int x,int y,int z,lint v=0) { if(es.count(v=hv(x,y,z))) return es[v];return INF; }
int main()
{
	int n=inn(),m;n=inn();lint ans=0;
	rep(i,1,n) a[i]=inn();m=inn();
	rep(i,1,m)
	{
		int u=inn(),v=inn(),r;lint c;
		while((r=gc)!='O'&&r!='R');c=inn();
		lint h=hv(u,v,r=='R');
		if(es.count(h)) es[h]=min(es[h],c);
		else es[h]=c;
	}
	rep(i,1,n-1)
	{
		t[i]=mp(a[i],a[i+1]);
		if(t[i].fir>t[i].sec) swap(t[i].fir,t[i].sec),d[i]=1;
		vec.pb(t[i]);
	}
	sort(vec.begin(),vec.end()),vec.erase(unique(vec.begin(),vec.end()),vec.end());
	rep(i,1,n-1) lst[lower_bound(vec.begin(),vec.end(),t[i])-vec.begin()].pb(d[i]);
	rep(i,0,(int)vec.size())
	{
		int x=vec[i].fir,y=vec[i].sec,a,b,cnt;lint ab,ba;
		lint A=E(x,y,0),B=E(y,x,0),AB=E(x,y,1),BA=E(y,x,1);
		A=min(A,AB),B=min(B,BA),AB=min(AB,A+B),BA=min(BA,B+A);
		if(AB<=BA) a=0,b=1,ab=AB,ba=BA;else a=1,b=0,ab=BA,ba=AB;
		memset(del,0,sizeof(int)*((int)lst[i].size())),cnt=0;
		Rep(j,lst[i])
			if(lst[i][j]==a) s[++cnt]=j;
			else if(cnt) ans+=ab,del[s[cnt]]=del[j]=1,cnt--;
		cnt=0;
		Rep(j,lst[i]) if(!del[j])
		{
			if(lst[i][j]==b) s[++cnt]=j;
			else if(cnt) ans+=ba,del[s[cnt]]=del[j]=1,cnt--;
		}
		Rep(j,lst[i]) if(!del[j]) ans+=(lst[i][j]==0?A:B);
	}
	return !printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83542511