【CERC2016】爵士之旅 Jazz Journey(贪心)

传送门

只用考虑2个点之间的情况
相当于就是一个0,10,1序列

可以删去0101100、1、01、10,每种价格不一样
求最小价格

设为a,b,ab,baa,b,ab,ba
a=min(a,ab),b=min(b,ba),ab=min(ab,a+b),ba=min(ba,b+a)a=min(a,ab),b=min(b,ba),ab=min(ab,a+b),ba=min(ba,b+a)

然后就先是0101或者0101,把便宜的那种所有都先删去
然后再把剩下的单个的删去即可

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
using namespace tr1;
const int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
} 
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define ll long long
#define re register
#define pb push_back
#define cs const 
#define pii pair<int,int>
#define fi first
#define se second
cs int N=300005;
cs int bas=192617;
vector<pii> p;
tr1::unordered_map<ll,ll> mp;
pii e[N];
int vis[N],d[N],s[N],a[N];
int n,m,q;
ll ans;
vector<int> last[N];
inline ll has(int a,int b,int c){
	return 1ll*a*bas*bas+1ll*b*bas+c;
}
inline ll query(int a,int b,int c){
	if(mp.count(has(a,b,c)))return mp[has(a,b,c)];return 2e9;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++)a[i]=read();
	q=read();
	for(int i=1;i<=q;i++){
		int u=read(),v=read();
		char ch=gc();
		while(ch!='O'&&ch!='R')ch=gc();
		ll now=has(u,v,ch=='R');
		ll c=read();
		if(mp.count(now))mp[now]=min(mp[now],c);
		else mp[now]=c;
	}
	for(int i=1;i<m;i++){
		e[i]=pii(a[i],a[i+1]);
		if(e[i].fi>e[i].se)swap(e[i].fi,e[i].se),d[i]=1;
		p.pb(e[i]);
	}
	sort(p.begin(),p.end()),p.erase(unique(p.begin(),p.end()),p.end());
	for(int i=1;i<m;i++)
		last[lower_bound(p.begin(),p.end(),e[i])-p.begin()].pb(d[i]);
	for(int i=0;i<p.size();i++){
		int u=p[i].fi,v=p[i].se,a=0,b=1,cnt,ab,ba;
		ll A=query(u,v,0),B=query(v,u,0),AB=query(u,v,1),BA=query(v,u,1);
		A=min(A,AB),B=min(B,BA),AB=min(AB,A+B),BA=min(BA,A+B);
		if(AB>BA) swap(a,b),swap(AB,BA);
		memset(vis,0,sizeof(int)*(last[i].size())),cnt=0;
		for(int j=0;j<last[i].size();j++){
			if(last[i][j]==a)s[++cnt]=j;
			else if(cnt)ans+=AB,vis[s[cnt]]=vis[j]=1,cnt--;
		}
		cnt=0;
		for(int j=0;j<last[i].size();j++){
			if(vis[j])continue;
			if(last[i][j]==b)s[++cnt]=j;
			else if(cnt)ans+=BA,vis[s[cnt]]=vis[j]=1,cnt--;
		}
		for(int j=0;j<last[i].size();j++)if(!vis[j])ans+=(last[i][j]==0?A:B);
	}
	cout<<ans;
}
posted @ 2019-07-25 18:37  Stargazer_cykoi  阅读(112)  评论(0编辑  收藏  举报