noip2013 提高組
阿新 • • 發佈:2017-07-15
還要 傳送門 hide one insert hid 數據 離散 algorithm
T1 轉圈遊戲 題目傳送門
果不其然 第一題還是模擬題 一波快速冪解決問題
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}View Codereturn ans*f; } int n,m,k,x; int qmod(int a,int b,int c){ int ans=1; while(b){ if(b&1) ans=ans*a%c; b=b/2; a=a*a%c; } return ans; } int main() { n=read(); m=read(); k=read(); x=read(); int v=qmod(10,k,n); printf("%d\n",(v*m+x)%n); return 0; }
T2 火柴排隊 題目傳送門
這是道樹狀數組求逆序數對的題目 當然還要加一波離散化就好了 不過這題的離散化很玄學哇 2333
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=100007,mod=99999997; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-View Code‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } struct node{int w,pos;}a[M],b[M]; bool cmp(node a,node b){return a.w<b.w;} int c[M],sum[M],n; LL ans; int lowbit(int x){return x&-x;} void insert(int x){ while(x<=n){ sum[x]++; x+=lowbit(x); } } int push_sum(int x){ int ans=0; while(x){ans+=sum[x]; x-=lowbit(x);} return ans; } int main() { n=read(); for(int i=1;i<=n;i++) a[i].w=read(),a[i].pos=i; for(int i=1;i<=n;i++) b[i].w=read(),b[i].pos=i; sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp); for(int i=1;i<=n;i++) c[a[i].pos]=b[i].pos; for(int i=1;i<=n;i++){ insert(c[i]); ans=(ans+i-push_sum(c[i]))%mod; } printf("%lld\n",ans); return 0; }
T3 貨車運輸 題目傳送門
幾乎是裸的lca吧 用lca維護一波最近公共祖先和路徑最小值就好了
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150007; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } int w[M],n,f[M][2]; int main() { n=read(); for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1; for(int i=1;i<=n;i++) for(int j=i-1;j;j--){ if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1); if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1); if(f[i][0]!=1&&f[i][1]!=1) break; } printf("%d\n",max(f[n][0],f[n][1])); return 0; }View Code
T4 積木大賽 題目傳送門
這道題就是我們只考慮相鄰兩列h1 h2 容易證明他的無後效性
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150007; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } int w[M],n,f[M][2]; int main() { n=read(); for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1; for(int i=1;i<=n;i++) for(int j=i-1;j;j--){ if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1); if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1); if(f[i][0]!=1&&f[i][1]!=1) break; } printf("%d\n",max(f[n][0],f[n][1])); return 0; }View Code
T5 花匠 題目傳送門
正解似乎是算拐點+1 數據隨機dp水過 0表示他是作為比較小的那個點 1則相反#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150007; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } int w[M],n,f[M][2]; int main() { n=read(); for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1; for(int i=1;i<=n;i++) for(int j=i-1;j;j--){ if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1); if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1); if(f[i][0]!=1&&f[i][1]!=1) break; } printf("%d\n",max(f[n][0],f[n][1])); return 0; }View Code
T6 華容道 題目傳送門
這道題黃學長都棄坑了 我糾結什麽呢 以後補吧 hzwer
noip2013 提高組