1. 程式人生 > >*LOJ#2134. 「NOI2015」小園丁與老司機

*LOJ#2134. 「NOI2015」小園丁與老司機

nbsp esp stream ons def put clas end noi

$n \leq 5e4$個平面上的點,從原點出發,能從當前點向左、右、上、左上或右上到達該方向最近的給定點。問三個問:一、最多經過多少點;二、前一問的方案;三、其所有方案種非左右走的邊至少要開幾輛挖掘機走完,挖掘機能從任意點出發,走路方式跟上面一樣。

前兩問:

縱坐標是增的可在不同層之間直接dp。同層的話,如果從左邊的點x到一個右邊的點y,那最優情況是x往左走,走到不能走再往右,直到y;從右邊的點走到左邊的點同理。dp後記一下前驅可以回答第二問。至於由誰轉移過來,可以用數據結構存一下$y$、$y+x$、$y-x$的值。

第三問:上下界最大流,不會。

技術分享圖片
  1 //#include<iostream>
2 #include<cstring> 3 #include<cstdio> 4 //#include<math.h> 5 #include<set> 6 //#include<queue> 7 //#include<bitset> 8 //#include<vector> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14
int qread() 15 { 16 char c; int s=0,f=1; while ((c=getchar())<0 || c>9) (c==-) && (f=-1); 17 do s=s*10+c-0; while ((c=getchar())>=0 && c<=9); return s*f; 18 } 19 20 //Pay attention to ‘-‘ , LL and double of qread!!!! 21 22 int n; 23 #define maxn 50011 24
struct Poi{int x,y,id; bool operator < (const Poi &b) const {return y<b.y || (y==b.y && x<b.x);} }p[maxn]; 25 26 struct snode{int v,id; bool operator < (const snode &b) const {return v<b.v;} }; 27 set<snode> s,s1,s2; 28 29 #define IT set<snode>::iterator 30 int f[maxn],pre[maxn],tt[maxn],ppt[maxn]; bool cf[maxn]; 31 32 int Ans[maxn],lans=0; 33 int main() 34 { 35 n=qread(); 36 for (int i=1;i<=n;i++) {p[i].x=qread(); p[i].y=qread(); p[i].id=i;} 37 sort(p+1,p+1+n); p[n+1].y=0x3f3f3f3f; p[0].y=-1; 38 f[0]=0; s.insert((snode){0,0}); s1.insert((snode){0,0}); s2.insert((snode){0,0}); 39 for (int i=1,j=1;i<=n;i++) 40 { 41 f[i]=-0x3f3f3f3f; 42 snode now=(snode){p[i].x,i}; IT it=s.lower_bound(now); 43 if (it!=s.end() && (*it).v==now.v) 44 { 45 if (f[i]<f[(*it).id]+1) {f[i]=f[(*it).id]+1; pre[i]=(*it).id; cf[i]=0;} 46 if (f[i]<tt[(*it).id]+1) {f[i]=tt[(*it).id]+1; pre[i]=(*it).id; cf[i]=1;} 47 s.erase(it); 48 }s.insert(now); 49 now=(snode){p[i].y-p[i].x,i}; it=s1.lower_bound(now); 50 if (it!=s1.end() && (*it).v==now.v) 51 { 52 if (f[i]<f[(*it).id]+1) {f[i]=f[(*it).id]+1; pre[i]=(*it).id; cf[i]=0;} 53 if (f[i]<tt[(*it).id]+1) {f[i]=tt[(*it).id]+1; pre[i]=(*it).id; cf[i]=1;} 54 s1.erase(it); 55 }s1.insert(now); 56 now=(snode){p[i].y+p[i].x,i}; it=s2.lower_bound(now); 57 if (it!=s2.end() && (*it).v==now.v) 58 { 59 if (f[i]<f[(*it).id]+1) {f[i]=f[(*it).id]+1; pre[i]=(*it).id; cf[i]=0;} 60 if (f[i]<tt[(*it).id]+1) {f[i]=tt[(*it).id]+1; pre[i]=(*it).id; cf[i]=1;} 61 s2.erase(it); 62 }s2.insert(now); 63 64 if (p[i].y!=p[i+1].y) 65 { 66 for (int k=j;k<=i;k++) tt[k]=ppt[k]=-0x3f3f3f3f; 67 for (int k=j+1,tmp=j,tot=1;k<=i;k++,tot++) 68 { 69 if (tt[k]<tot+f[tmp]) {tt[k]=tot+f[tmp]; ppt[k]=tmp;} 70 if (f[k]>f[tmp]) tmp=k; 71 } 72 for (int k=i-1,tmp=i,tot=1;k>=j;k--,tot++) 73 { 74 if (tt[k]<tot+f[tmp]) {tt[k]=tot+f[tmp]; ppt[k]=tmp;} 75 if (f[k]>f[tmp]) tmp=k; 76 } 77 j=i+1; 78 } 79 // cout<<p[i].id<<‘ ‘<<f[i]<<‘ ‘<<pre[i]<<‘ ‘<<cf[i]<<endl; 80 } 81 82 int ans=0,id=0; bool ccf=0; 83 for (int i=1;i<=n;i++) if (f[i]>ans) ans=f[i],ccf=0,id=i; 84 for (int i=1;i<=n;i++) if (tt[i]>ans) ans=tt[i],ccf=1,id=i; 85 printf("%d\n",ans); 86 int x=id; 87 while (x) 88 { 89 Ans[++lans]=p[x].id; 90 if (!ccf) {ccf^=cf[x]; x=pre[x];} 91 else 92 { 93 int y=ppt[x]; ccf=0; 94 if (y>x) 95 { 96 for (int j=x+1;j<y;j++) Ans[++lans]=p[j].id; 97 for (int j=y;j<=n+1;j++) if (p[j].y!=p[y].y) 98 {for (int k=j-1;k>y;k--) Ans[++lans]=p[k].id; break;} 99 } 100 else 101 { 102 for (int j=x-1;j>y;j--) Ans[++lans]=p[j].id; 103 for (int j=y;j>=0;j--) if (p[j].y!=p[y].y) 104 {for (int k=j+1;k<y;k++) Ans[++lans]=p[k].id; break;} 105 } 106 x=y; 107 } 108 } 109 for (int i=lans;i>1;i--) printf("%d ",Ans[i]); printf("%d\n",Ans[1]); 110 // puts(""); 111 puts("3"); 112 return 0; 113 }
View Code

*LOJ#2134. 「NOI2015」小園丁與老司機