我们看完题目,大概都会有点想法,我们可以不断地贪心插入这个任务
实际上就是,我们把这些任务和对面的时间点看成一个二分图,于是我们可以思考二分图匹配,并用二分来查找时间点,类似匈牙利的思想把任务往后挤,挤不动就不插入
最开始的时候并没有看FQW的论文,然后稀里糊涂的写了一段又臭又长的代码,WA了。
FQW的实现还是比较简单的,而且那篇论文里面几乎把各种优化统统列出来了。
总体复杂度(N2),记得ans要是long long的,不然就会像我一样找了好久找不到措
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define N 5005 #define inf 1000000007 struct dian { int be,en,v; }d[N]; int f[N],b[N]; //bool v[N]; int n; LL ans=0; bool timecom(dian a,dian b) { if (a.be==b.be) return a.en<b.en; else return a.be<b.be; } bool vcom(dian a,dian b) { return a.v>b.v; } void lishan() { sort(d+1,d+n+1,timecom); int t=0; fo(i,1,n) { t=max(t+1,d[i].be); b[i]=t; } b[n+1]=inf; } int erfen(int k,int l,int r) { // cout<<d[k].be<<' '<<d[k].en<<' '<<l<<' '<<r<<' '<<b[l]<<' '<<b[r]<<' '<<endl; int mid=(l+r)>>1; if(d[k].be<=b[mid]&&b[mid]<=d[k].en) { while(d[k].be<=b[mid]) mid--; return mid+1; } if(d[k].be<=b[mid]) return erfen(k,l,mid-1); if(b[mid]<=d[k].en) return erfen(k,mid+1,r); } bool match(int k,int x) { if(d[k].en<b[x])return 0; if(f[x]==0) { f[x]=k; return 1; } if(d[k].en>d[f[x]].en) return match(k,x+1); else { if(match(f[x],x+1)) { f[x]=k; return 1; } } return 0; } void work() { sort(d+1,d+n+1,vcom); fo(i,1,n) { int j=erfen(i,1,n); // cout<<i<<' '<<j<<' '<<n<<endl; if(match(i,j))ans+=d[i].v; // cout<<ans<<' '<<d[i].v<<endl; } } int main() { n=read(); fo(i,1,n) { d[i].be=read(); d[i].en=read(); d[i].v=read(); } lishan(); work(); cout<<ans<<endl; return 0; }