[題解]CF1399F Yet Another Segments Subset
阿新 • • 發佈:2020-08-06
昨天晚上沒打,今天來看一看題
錯失上 \(rating\) 好機會
我們把這道題看成兩部分
第一部分:計算出選每個線段能獲得的權值
第二部分:根據第一部分的結果 \(DP\)
第二部分很好求,這道題的難點主要在第一部分
我們將區間按照長度排序,對於每一個區間做一次與第二部分類似的 \(DP\)
就可以得到選每個線段能得到的權值
然後 \(DP\) 就可以了
程式碼(我的實現有點鬼畜)
#include<bits/stdc++.h> #include <cstdio> clock_t clk=clock(); namespace IO { using namespace std; char buf[1<<22],Out[1<<22],*p1=buf,*p2=buf; int p3=-1,f=0; inline void file() { #ifdef NTFOrz freopen("file.in","r",stdin); #endif } inline char getchar() { return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++; } inline void flush(){fwrite(Out,1,p3+1,stdout),p3=-1;} inline void check(){if (p3>(1<<21)) flush();} inline void putchar(char a){Out[++p3]=a;check();} inline void put(string s) { int tmp=p3; while (p3-tmp<s.size()) putchar(s[p3-tmp]); } inline char gc() { char c=getchar(); while (!c||c=='\n'||c==' ') c=getchar(); return c; } inline void getc(char *ch) { char c=getchar();int p=-1; while (!c||c=='\n'||c==' ') c=getchar(); while (!(!c||c=='\n'||c==' ')) ch[++p]=c,c=getchar(); } inline void chktime() { #ifdef NTFOrz printf("%dms\n",clock()-clk); #endif } } namespace my_std { using namespace std; #define getchar IO::getchar #define putchar IO::putchar #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #define Re register #define rep(i,a,b) for (Re int i=(a);i<=(b);i++) #define drep(i,a,b) for (Re int i=(a);i>=(b);i--) #define repv(i,v) for (Re int i=0;i<v.size();i++) #define go(u) for (Re int i=head[(u)];i;i=e[i].nxt) #define writesp(x) write(x),putchar(' '),IO::check() #define writeln(x) write(x),putchar('\n'),IO::check() #define mem(x,v) memset(x,v,sizeof(x)) #define pb push_back #define fir first #define sec second #define MP make_pair typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int INF=0x7fffffff; inline int read() { int sum=0,f=0;char c=getchar(); while (!isdigit(c)) f|=(c=='-'),c=getchar(); while (isdigit(c)) sum=(sum<<1)+(sum<<3)+(c^48)%998244353,c=getchar(); return f?-sum:sum; } void write(int k) { if (k<0) putchar('-'),k=-k; if (k>=10) write(k/10); putchar(k%10+48); } #define templ template<typename T> templ inline void chkmax(T &x,T y){if (x<y) x=y;} templ inline void chkmin(T &x,T y){if (x>y) x=y;} mt19937 rng(time(NULL)); templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);} } using namespace my_std; const int N=300010; int n,m,f[N]; vector<pii>v[N]; vector<int>vv[N]; struct node{int l,r,val;}p[N]; inline bool cmp1(node a,node b){return a.l<b.l;} inline bool cmp2(node a,node b){return a.r<b.r;} inline bool cmp3(node a,node b){return a.r-a.l<b.r-b.l;} int main() { IO::file(); int T=read(); while (T--) { n=read(),m=0,mem(f,0); rep(i,1,n) p[i].l=read(),p[i].r=read(),p[i].val=0,chkmax(m,p[i].r); rep(i,1,m) v[i].clear(),vv[i].clear(); sort(p+1,p+n+1,cmp3); rep(i,1,n) vv[p[i].r].pb(i); rep(i,1,n) { mem(f,0); int l=p[i].l,r=p[i].r; rep(j,l,r) { f[j]=f[j-1]; repv(k,vv[j]) { if (p[vv[j][k]].l>=l&&(k!=r||p[vv[j][k]].l!=l)) { chkmax(f[j],f[p[vv[j][k]].l-1]+p[vv[j][k]].val); } } } p[i].val=f[r]+1; } mem(f,0); rep(i,1,n) v[p[i].r].pb(MP(p[i].l,p[i].val)); rep(i,1,m) { f[i]=f[i-1]; repv(j,v[i]) { int l=v[i][j].fir,w=v[i][j].sec; chkmax(f[i],f[l-1]+w); } } writeln(f[m]); } IO::flush(); IO::chktime(); return 0; }