NOIP2013题解+总结

来源:互联网 发布:dedecms sql 变量 编辑:程序博客网 时间:2024/06/08 09:15

Day1

T1 水题,快速幂

#include<cmath>#include<cstdio>#include<string>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;class DREAD{public:int Int(){ int x;read(x);return x; }private:bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }void read(int &x){char ch;bool pos=1;x=0;while (ch=getchar())if (isdigit(ch) || ch=='-'){if (ch=='-') ch=getchar(),pos=0;break;}for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';if (!pos) x=-x;}}READ;int N,M,K,X;LL power(LL a,int b){if (!b) return 1;if (b==1) return a;LL tmp=power(a,b/2);tmp=((tmp%N)*(tmp%N))%N;if (b%2==0) return tmp; else return (tmp*a)%N;}int main(){N=READ.Int(),M=READ.Int(),K=READ.Int(),X=READ.Int();LL tmp=power(10,K);tmp%=N;cout<<(X+(tmp*(LL)M)%N)%N<<endl;return 0;}

T2排序求逆序对,本来考场上已经往这方面想了,但是最后还是没写写了个60分暴力结果挂了,正解代码:

#include<cstdio>#include<algorithm>using namespace std;typedef pair<int,int> PII;#define MP make_pairclass DREAD{public:int Int(){ int x;read(x);return x; }private:bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }void read(int &x){char ch;x=0;while (ch=getchar()) if (isdigit(ch)) break;for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';}}READ;template <typename Type> class T_SUM_BIT{/*--BIT->Binary Indexed Tree--*/public:static const int SIZE=100000+10;Type t[SIZE],sum[SIZE];int real_size;void Init(int size){ real_size=size; }void Build(int size){real_size=size;for (int i=1; i<=real_size; ++i) t[i]=sum[i]-sum[i-lowbit(i)];}void Modify(int idx,int delta){for (int p=idx; p<=real_size; p+=lowbit(p)) t[p]+=delta;}Type Query(int idx){Type res=0;for (int p=idx; p; p-=lowbit(p)) res+=t[p];return res;}private:int lowbit(int idx){ return idx&-idx; }};class PROGRAM{public:void Open(){ freopen("data.in","r",stdin); }void Init(){N=READ.Int();for (int i=1; i<=N; ++i) a[i].first=READ.Int(),a[i].second=i;for (int i=1; i<=N; ++i) b[i].first=READ.Int(),b[i].second=i;}void Work(){sort(a+1,a+N+1);sort(b+1,b+N+1);for (int i=1; i<=N; ++i) rank[b[i].second]=a[i].second;bit.Init(N);int res=0;for (int i=N; i>=1; --i){res+=bit.Query(rank[i]-1);res%=mod;bit.Modify(rank[i],1);}printf("%d\n", res%mod);}private:static const int N_MAX=100000+10,mod=99999997;int N,rank[N_MAX];PII a[N_MAX],b[N_MAX];T_SUM_BIT<int> bit;}PROG;int main(){//PROG.Open();PROG.Init();PROG.Work();return 0;}

T3最大生成树+LCA,考场上没想出来,写的暴力挂掉了,正解代码:

#include<cstdio>#include<vector>#include<cstring>#include<algorithm>using namespace std;#define it(type) vector<type>::iteratorclass DREAD{public:int Int(){ int x;read(x);return x; }private:bool isdigit(char ch){ return '0'<=ch && ch<='9'; }void read(int &x){char ch;x=0;while (ch=getchar()) if (isdigit(ch)) break;for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';}}READ;struct Tedge{int a,b,c;Tedge(){}Tedge(int _a,int _b,int _c):a(_a),b(_b),c(_c){}};bool cmp_edge(const Tedge &a,const Tedge &b){ return a.c>b.c; }vector<Tedge> edge;const int N_MAX=10000+10,M_MAX=100000+10,K_MAX=15,inf=~0u>>1;int N,M;void Init(){N=READ.Int();M=READ.Int();for (int i=1; i<=M; ++i){int a=READ.Int(),b=READ.Int(),c=READ.Int();edge.push_back(Tedge(a,b,c));}}int now[N_MAX],pre[M_MAX],son[M_MAX],v[M_MAX],tot=0;bool vis[N_MAX];inline void add(int a,int b,int c){ pre[++tot]=now[a];now[a]=tot;son[tot]=b;v[tot]=c; }inline void con(int a,int b,int c){ add(a,b,c);add(b,a,c); }int fa[N_MAX];int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); }void Kruscal(){sort(edge.begin(),edge.end(),cmp_edge);for (int i=1; i<=N; ++i) fa[i]=i;int select=0;for (it(Tedge) i=edge.begin(); i!=edge.end(); ++i){int x=find(i->a),y=find(i->b);if (x==y) continue;fa[x]=y;con(x,y,i->c);if (++select==N-1) return;}}struct Tmultiple{int anc,min;Tmultiple(){}Tmultiple(int _anc,int _min):anc(_anc),min(_min){}}mul[N_MAX][K_MAX];int dep[N_MAX];void Dfs(int x){vis[x]=1;for (int p=now[x]; p; p=pre[p])if (!vis[son[p]]){dep[son[p]]=dep[x]+1;mul[son[p]][0]=Tmultiple(x,v[p]);for (int i=1; i<K_MAX; ++i){mul[son[p]][i].anc=mul[mul[son[p]][i-1].anc][i-1].anc;mul[son[p]][i].min=min(mul[son[p]][i-1].min,mul[mul[son[p]][i-1].anc][i-1].min);}Dfs(son[p]);}}int Answer(int a,int b){if (find(a)!=find(b)) return -1;int res=inf;if (dep[a]<dep[b]) swap(a,b);for (int i=K_MAX-1; i>=0; --i)if (dep[a]-(1<<i)>=dep[b]){res=min(res,mul[a][i].min);a=mul[a][i].anc;}for (int i=K_MAX-1; i>=0; --i)if (mul[a][i].anc!=mul[b][i].anc){res=min(res,min(mul[a][i].min,mul[b][i].min));a=mul[a][i].anc;b=mul[b][i].anc;}if (a!=b) return res=min(res,min(mul[a][0].min,mul[b][0].min));return res;}void Solve(){Kruscal();memset(vis,0,sizeof(vis));for (int i=1; i<=N; ++i)if (!vis[i]){dep[i]=0;Dfs(i);}int Q=READ.Int();for (int i=1; i<=Q; ++i){int a=READ.Int(),b=READ.Int();printf("%d\n", Answer(a,b));}}int main(){Init();Solve();return 0;}


-------------------------------------分割线------------------------------------------

Day1总结:考场上写第二题的时候有点乱,想的时候脑子一团糟,最后写了个60分的暴力,为了写第三题自己生了两组小数据后就没check了,结果昨天测了民间数据后发现暴力挂了,丢了60分,十分不爽。第三题考场上没想出来,也没check,再丢60。。。。。。如果第一天有220,那省一就毫无压力了。Day1的惨痛经历告诉我,不要过分相信自己的感觉,在考场上一定要稳,既然写了部分分,就一定要拿到,如果考完了发现部分分挂了,那还不如用写部分分的时间想正解。

-------------------------------------分割线-------------------------------------------

Day2

T1是USACO2013MAR的原题Poker Hands,考前做过一遍,结果考场上没想起来,70分暴力幸好没挂正解代码:

#include<cstdio>using namespace std;inline bool isdigit(char ch){return ('0'<=ch && ch<='9');}inline int read(){char ch;int tmp=0;while (ch=getchar()) if (isdigit(ch)) break;for (; isdigit(ch); ch=getchar()) tmp=tmp*10+ch-'0';return tmp;}inline void write(int &ans){char ch[9];int tot=0;while (ans) ch[++tot]=ans%10+'0',ans/=10;for (int i=tot; i>=1; --i) putchar(ch[i]);puts("");}int main(){int n=read(),ans=0;for (int i=1,num=0,pre=0; i<=n; ++i,pre=num){num=read();if (num>pre) ans+=num-pre;}write(ans);return 0;}
T2贪心或者线段树优化DP,我考场上写的是贪心,直接O(n)取出每个单调区间的最高点和最低点再求答案

#include<cmath>#include<cstdio>#include<string>#include<vector>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;typedef pair<int,int> PII;#define MP make_pairclass DREAD{public:int Int(){ int x;read(x);return x; }private:bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }void read(int &x){char ch;bool pos=1;x=0;while (ch=getchar())if (ch=='-' || isdigit(ch)){if (ch=='-') ch=getchar(),pos=0;break;}for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';if (!pos) x=-x;}}READ;const int N_MAX=100000+10;int N,a[N_MAX];struct Tseg{int first,second,flag;Tseg(){}Tseg(int _first,int _second,int _flag):first(_first),second(_second),flag(_flag){}};vector<Tseg> vec;enum Ttype{DEC,INC};int DOA(){int res=1;if (vec[0].flag==DEC) res+=vec.size()-1;else res+=vec.size();return res;}int DOB(){int res=1;if (vec[0].flag==INC) res+=vec.size()-1;else res+=vec.size();return res;}int main(){N=READ.Int();if (N==1){ puts("1");return 0; }if (!N){ puts("0");return 0; }for (int i=1; i<=N; ++i) a[i]=READ.Int();int BP;for (int i=1; i<=N; ++i) if (a[i]!=a[i+1]){BP=i;break;}int flag=(a[BP+1]>a[BP]),L=1,R;for (int i=BP+2; i<=N; ++i){if (flag){if (a[i]<a[i-1]){flag=DEC;vec.push_back(Tseg(L,i-1,INC));L=i-1;}}else{if (a[i]>a[i-1]){flag=INC;vec.push_back(Tseg(L,i-1,DEC));L=i-1;}}}if (L!=N) vec.push_back(Tseg(L,N,flag));int res1=DOA(),res2=DOB();printf("%d\n", res1>res2?res1:res2);return 0;}
T3对正解不明觉厉,直接乱搞,不知道多少分。。。

-------------------------------------分割线-----------------------------------------

Day2总结:Day2比Day1考的要好一些,虽然第一题没想到正解,但至少拿了70分暴力

-------------------------------------分割线-----------------------------------------

这次NOIP总体来说是挂了,原本预计400结果只有270,一等是没希望了,只有吸取这次的教训,为以后的比赛积累经验。考场上要尽量保持KISS原则,结果D1T2的暴力却写的十分冗长。总的来说考场上还是应该以得分为主。另外就当是为今年的省选攒RP吧。。。