NOIP模擬16
阿新 • • 發佈:2021-07-16
期望得分:0+20+40=60
實際得分:10+20+50=80
全打的暴力
T1 ,不會做,亂搞,求的每組點和點,點和上下邊的距離的一半,然後操作一下把樣例騙過去,水了十分
正解:每條到終點的路徑不可避免地會經過連線,要求的最小距離的最大值,計算最小距離可以求出連線的最小生成樹,這樣的話計算每條由頂端到底端的路徑,對每條路徑取最大值,所有路徑的最大值上取最小值
T2,小資料搞個狀壓,特殊性質不會搞
正解:求極大上升序列,dp,f[i]表示最後一個選的 i,每次求 i 之前,其對應值小於 i 的 且遞增的 j 取最小值,這樣可以保證不相交且極大
把第二維 j 放在樹上維護上升序列就好了,複雜度我不會算,題解說是\(O(nlog^2n)\)
T3,直接一路上去找父親,並維護最小值,小資料沒問題,20pts,隨機資料跑5e5沒問題,20pts,然後估分40,沒想到有個500多的亂入大資料,,,
正解:維護下凸包和可持久化棧,知識點沒學,還不會
T1
#include<bits/stdc++.h> using namespace std; const int N=6002; struct pot_{ int x,y; friend bool operator<(pot_ a,pot_ b) { return a.x<b.x; } }pot[N]; struct line{ int u,v; double w; friend bool operator<(line a,line b) { return a.w<b.w; } }edge[N*(N-1)/2+1]; struct qxxx{ int v,next; double w; }cc[2*N]; double ans=0x7fffffff; int n,m,k,ed_n; int f[N]; int first[N],cnt; bool jud[N]; inline int read() { int s=0; char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s; } void qxx(int u,int v,double w) { cc[++cnt].v=v; cc[cnt].w=w; cc[cnt].next=first[u]; first[u]=cnt; return; } int find(int x) { if(f[x]==x) return x; return f[x]=find(f[x]); } void kruscal() { sort(edge+1,edge+ed_n+1); for(int i=1;i<=ed_n;i++) { int x=find(edge[i].u); int y=find(edge[i].v); if(x!=y) { f[x]=y; qxx(edge[i].u,edge[i].v,edge[i].w); qxx(edge[i].v,edge[i].u,edge[i].w); } } return; } void dfs(int x,double w) { jud[x]=1; int s=0; for(int i=first[x];i;i=cc[i].next) if(!jud[cc[i].v]) { dfs(cc[i].v,max(cc[i].w,w)); s++; } if(!s) { ans=min(ans,max(w,(double)pot[x].y/2)); return; } return; } int main() { n=read(); m=read(); k=read(); for(int i=1;i<=k;i++) { pot[i].x=read(); pot[i].y=read(); f[i]=i; } f[0]=0; sort(pot+1,pot+k+1); for(int i=1;i<=k;i++) { int sl=min(i+300,k); for(int j=i+1;j<=sl;j++) { edge[++ed_n].u=i; edge[ed_n].v=j; edge[ed_n].w=sqrt(fabs(pot[i].x-pot[j].x)*fabs(pot[i].x-pot[j].x)+fabs(pot[i].y-pot[j].y)*fabs(pot[i].y-pot[j].y)); } } for(int i=1;i<=k;i++) { edge[++ed_n].u=0; edge[ed_n].v=i; edge[ed_n].w=m-pot[i].y; } kruscal(); dfs(0,0); printf("%.10lf",ans/2); return 0; }
T2
#include<bits/stdc++.h> using namespace std; const int N=200011; struct tree{ int l,r; int sum; int key; }tre[4*N]; int n; int pot[N],c[N]; int rle[N]; int dp[N]; inline int read() { int s=0; char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s; } void build(int i,int l,int r) { tre[i].l=l; tre[i].r=r; if(l==r) return; int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); return; } void updata(int i) { tre[i].key=max(tre[i<<1].key,tre[i<<1|1].key); return; } void insert(int i,int x,tree val) { if(tre[i].l==tre[i].r) { tre[i].sum=val.sum; tre[i].key=val.key; return; } int mid=(tre[i].l+tre[i].r)>>1; if(mid>=x) insert(i<<1,x,val); else insert(i<<1|1,x,val); updata(i); return; } tree query(int i,int x,int lim) { tree ans,ans1,ans2; ans.sum=0x7fffffff; ans.key=0; if(tre[i].l==tre[i].r) return tre[i]; if(tre[i].r<=x) { if(tre[i].key<=lim) return ans; int mid=(tre[i].l+tre[i].r)>>1; if(tre[i<<1|1].key<=lim) return query(i<<1,x,lim); if(tre[i<<1].key<=lim||tre[i<<1].key<tre[i<<1|1].key) return query(i<<1|1,x,lim); ans1=query(i<<1|1,x,lim); if(ans1.key) { ans2=query(i<<1,x,ans1.key); ans.key=ans2.key; ans.sum=min(ans2.sum,ans1.sum); return ans; } else return query(i<<1,x,lim); } else { if(tre[i].key<=lim) return ans; int mid=(tre[i].l+tre[i].r)>>1; if(mid+1>x) return query(i<<1,x,lim); else { if(tre[i<<1].key<=lim) return query(i<<1|1,x,lim); if(tre[i<<1|1].key<=lim) return query(i<<1,x,lim); ans1=query(i<<1|1,x,lim); if(ans1.key) { ans2=query(i<<1,x,ans1.key); ans.key=max(ans1.key,ans2.key); ans.sum=min(ans2.sum,ans1.sum); return ans; } else return query(i<<1,x,lim); } } return ans; } int main() { n=read(); for(int i=1;i<=n;i++) rle[pot[i]=read()]=i; for(int i=1;i<=n;i++) c[i]=read(); build(1,1,n); tree ans; ans.sum=c[1]; ans.key=1; insert(1,pot[1],ans); dp[1]=c[1]; for(int i=2;i<=n;i++) { ans=query(1,pot[i]-1,0); if(ans.sum<0x7fffffff) dp[i]=c[i]+ans.sum; else dp[i]=c[i]; ans.key=i; ans.sum=dp[i]; insert(1,pot[i],ans); } int lim=pot[n]; dp[0]=dp[n]; for(int i=n-1;i;i--) if(pot[i]>lim) { dp[0]=min(dp[0],dp[i]); lim=pot[i]; } cout<<dp[0]<<endl; return 0; }