1. 程式人生 > >[CERC2016] bzoj 4795 爵士之旅 Jazz Journey - 貪心

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