[CERC2016] bzoj 4795 爵士之旅 Jazz Journey - 貪心
阿新 • • 發佈:2018-11-01
題目大意:
轉化後是給一個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);
}