Day1:
T1:模拟;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 using namespace std; 14 #define FILE "toy" 15 #define up(i,j,n) for(int i=(j);i<=(n);i++) 16 #define pii pair<int,int> 17 #define LL long long 18 namespace IO{ 19 char buf[1<<15],*fs,*ft; 20 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 21 int read(){ 22 int ch=gc(),f=0,x=0; 23 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 24 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 25 return f?-x:x; 26 } 27 }using namespace IO; 28 const int maxn=101000; 29 int n,m; 30 int a[maxn]; 31 char s[maxn][20]; 32 int main(){ 33 freopen(FILE".in","r",stdin); 34 freopen(FILE".out","w",stdout); 35 scanf("%d%d",&n,&m); 36 up(i,0,n-1)scanf("%d %s",&a[i],s[i]); 37 int x,y,now=0; 38 up(i,1,m){ 39 scanf("%d%d",&x,&y); 40 if(x==a[now])now=(now-y+n)%n; 41 else now=(now+y)%n; 42 } 43 printf("%s",s[now]); 44 return 0; 45 } 46
T2:
这次noip2016最难的题?
考场上只急着打暴力了,没有好好思考;
实际上想了之后还是很简单的;
这题的关键是理清思路,题目上的特点是 若一条路径已走的时间若与当前节点的值相等,这一点的答案加1;
最暴力的思路当然是dfs Q遍,先判断这个点是否在这条路径上,然后判断已走的距离是不是等于当前点的权值,都符合的话ans++;
如何化简条件?
我们可以发现当若有一条从x->y的路径是一条链,且dep[x]<dep[y],则若dep[i]-dep[x]=v[i],则该点ans++;
这可以变形成dep[i]-v[i]=dep[x],左边只与点i自身有关;
经过了这样的转化,我们发现可以这样做,将一个路径拆成从x->lca和lca->y两个链,然后可以仿照上面的方法,用dep与v[i]的关系做。
但做到了这一步仍然没什么卵用;
我们是否可以把目光转移,从看一条路径到看每个点?
对每个点而言,我们需要计算的是,它自身dep[i]±v[i]正好匹配经过它的路径所要求的的值的路径的数目;
这很绕,实际上对路径只有两个要求,第一个是经过它,第二个是路径与这个点可以匹配;
怎么维护?
第一个,维护只经过它的路径的值的集合;
第二个,在集合中快速找到符合要求的值的数目;
满足这两个要求,第一个可以用离线的方法维护,第二个可以在dfs的途中顺便维护一个桶,这个桶里存的就是经过它的路径的值的集合,然后可以O(1)查询;
这里面还有一个地方需要注意,每次桶从一颗子树出来的时候会带着这颗子树的信息,再进入另一个桶的时候会出现问题,解决方案是作差,先记录一下当前的ans值,待遍历完所有子树,再记录一下当前的ans,两个的差值即为所求;
在大佬眼里就是道水题...
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 #include<queue> 14 using namespace std; 15 #define FILE "dealing" 16 #define up(i,j,n) for(int i=(j);i<=(n);i++) 17 #define pii pair<int,int> 18 #define LL long long 19 namespace IO{ 20 char buf[1<<15],*fs,*ft; 21 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 22 int read(){ 23 int ch=gc(),f=0,x=0; 24 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 25 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 26 return f?-x:x; 27 } 28 }using namespace IO; 29 const int maxn=600010; 30 int n,m; 31 struct node{ 32 int y,next,v; 33 }e[maxn],u[maxn],v[maxn],q[maxn]; 34 int headu[maxn],headv[maxn],headq[maxn],lenu,lenv,lenq; 35 int linkk[maxn],len=0; 36 int s[maxn],t[maxn],w[maxn]; 37 inline void insert(int x,int y,node* e,int* linkk,int& len,int v){e[++len].y=y;e[len].v=v;e[len].next=linkk[x];linkk[x]=len;} 38 int top[maxn],siz[maxn],son[maxn],fa[maxn],dep[maxn],Lca[maxn],dfs_clock=0; 39 int f[maxn],flag[maxn]; 40 int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} 41 int pre[maxn],low[maxn],id[maxn]; 42 void tarjan(int x){ 43 siz[x]=1; 44 pre[x]=++dfs_clock; 45 id[dfs_clock]=x; 46 flag[x]=1; 47 for(int i=linkk[x];i;i=e[i].next){ 48 if(e[i].y==fa[x])continue; 49 fa[e[i].y]=x; 50 dep[e[i].y]=dep[x]+1; 51 tarjan(e[i].y); 52 } 53 for(int i=headq[x];i;i=q[i].next){ 54 if(Lca[q[i].v])continue; 55 if(flag[q[i].y]==1)Lca[q[i].v]=q[i].y; 56 else if(flag[q[i].y]==2)Lca[q[i].v]=getf(q[i].y); 57 } 58 f[x]=fa[x]; 59 flag[x]=2; 60 low[x]=++dfs_clock; 61 id[dfs_clock]=x; 62 } 63 void init(){ 64 n=read(),m=read(); 65 int x,y; 66 up(i,1,n-1){x=read(),y=read();insert(x,y,e,linkk,len,0);insert(y,x,e,linkk,len,0);} 67 up(i,1,n)w[i]=read(); 68 up(i,1,m){ 69 s[i]=read(),t[i]=read(); 70 insert(s[i],t[i],q,headq,lenq,i); 71 insert(t[i],s[i],q,headq,lenq,i); 72 } 73 up(i,1,n)f[i]=i; 74 tarjan(1); 75 } 76 inline void make_tag(int s,int t,int st,bool flag){ 77 if(flag){ 78 insert(s,st,u,headu,lenu,1); 79 insert(t,st,u,headu,lenu,-1); 80 } 81 else { 82 insert(s,st,v,headv,lenv,1); 83 insert(t,st,v,headv,lenv,-1); 84 } 85 } 86 int ans[maxn]; 87 int cnt1[maxn<<3],cnt2[maxn<<3]; 88 int l[maxn]; 89 void slove(){ 90 up(i,1,m){ 91 if(Lca[i]==s[i])make_tag(fa[s[i]],t[i],dep[s[i]],0); 92 else if(Lca[i]==t[i])make_tag(s[i],fa[t[i]],dep[s[i]],1); 93 else { 94 make_tag(s[i],fa[Lca[i]],dep[s[i]],1); 95 make_tag(Lca[i],t[i],2*dep[Lca[i]]-dep[s[i]],0); 96 } 97 } 98 memset(flag,0,sizeof(flag)); 99 int x; 100 for(int i=1;i<=dfs_clock;i++){ 101 x=id[i]; 102 if(flag[x]){ 103 for(int i=headu[x];i;i=u[i].next){ 104 if(u[i].v==-1)cnt1[u[i].y+maxn]--; 105 else cnt1[u[i].y+maxn]++; 106 } 107 for(int i=headv[x];i;i=v[i].next){ 108 if(v[i].v==1)cnt2[v[i].y+maxn]--; 109 else cnt2[v[i].y+maxn]++; 110 } 111 ans[x]=cnt1[dep[x]+w[x]+maxn]+cnt2[dep[x]-w[x]+maxn]-l[x]; 112 } 113 else { 114 l[x]=cnt1[dep[x]+w[x]+maxn]+cnt2[dep[x]-w[x]+maxn]; 115 flag[x]=1; 116 } 117 } 118 up(i,1,n)printf("%d%c",ans[i],i==n?‘\n‘:‘ ‘); 119 } 120 int main(){ 121 freopen(FILE".in","r",stdin); 122 freopen(FILE".out","w",stdout); 123 init(); 124 slove(); 125 return 0; 126 }
顺便进行了一下求lca的速度测试:
只求LCA的话,树链剖分最快,tarjan次之,倍增最慢(经常被卡);
还需要一些附加信息的话,tarjan无法处理,树链剖分效率很好,倍增效率太低;
代码长度上,树链剖分最长,lca次之,tarjan最短;
如果考场上只求lca的话,建议tarjan,很好写;
T3:
无力吐槽,这题让一心一意备考noip的人怎么受得了;
概率dp;
把概率扒下来其实就是一背包动规;
具体的还是自己去体会(看代码)......
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 #include<queue> 14 using namespace std; 15 #define FILE "dealing" 16 #define up(i,j,n) for(int i=(j);i<=(n);i++) 17 #define pii pair<int,int> 18 #define LL long long 19 #define db double 20 namespace IO{ 21 char buf[1<<15],*fs,*ft; 22 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 23 int read(){ 24 int ch=gc(),f=0,x=0; 25 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 26 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 27 return f?-x:x; 28 } 29 }using namespace IO; 30 const int maxn=2020; 31 const db inf=100000000.0; 32 int n,m,v,e,a[maxn],b[maxn]; 33 db k[maxn]; 34 int d[maxn][maxn]; 35 void init(){ 36 scanf("%d%d%d%d",&n,&m,&v,&e); 37 memset(d,10,sizeof(d)); 38 up(i,1,v)d[i][i]=0; 39 up(i,1,n)scanf("%d",&a[i]); 40 up(i,1,n)scanf("%d",&b[i]); 41 up(i,1,n)scanf("%lf",&k[i]); 42 int x,y,vv; 43 up(i,1,e){ 44 scanf("%d%d%d",&x,&y,&vv); 45 if(d[x][y]>vv)d[x][y]=d[y][x]=vv; 46 } 47 up(g,1,v)up(i,1,v)up(j,1,v)if(d[i][g]+d[g][j]<d[i][j])d[i][j]=d[i][g]+d[g][j]; 48 } 49 db f[2020][2020][2]; 50 void slove(){ 51 up(i,1,n)up(j,0,m)f[i][j][0]=f[i][j][1]=inf; 52 f[1][1][1]=f[1][0][0]=0; 53 db duu,duv,dvu,dvv,ans=inf; 54 up(i,2,n)for(int j=0;j<=i&&j<=m;j++){ 55 duu=d[a[i-1]][a[i]],duv=d[a[i-1]][b[i]],dvu=d[b[i-1]][a[i]],dvv=d[b[i-1]][b[i]]; 56 if(j!=i)f[i][j][0]=min(f[i-1][j][1]+duu*(1-k[i-1])+dvu*k[i-1],duu+f[i-1][j][0]); 57 if(j)f[i][j][1]=min(f[i-1][j-1][1]+duu*(1-k[i-1])*(1-k[i])+duv*(1-k[i-1])*k[i]+dvv*k[i]*k[i-1]+dvu*k[i-1]*(1-k[i]),f[i-1][j-1][0]+duv*k[i]+duu*(1-k[i])); 58 } 59 for(int i=0;i<=m;i++)ans=min(ans,min(f[n][i][0],f[n][i][1])); 60 printf("%.2lf\n",ans); 61 } 62 int main(){ 63 freopen(FILE".in","r",stdin); 64 freopen(FILE".out","w",stdout); 65 init(); 66 slove(); 67 return 0; 68 }
Day2:
T1:
组合数,考场脑子一抽写了二维树状数组,但实际也没什么问题(实际这题的二维动规是有一定的风险的,有人因此挂了);
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 using namespace std; 14 #define FILE "problem" 15 #define up(i,j,n) for(int i=(j);i<=(n);i++) 16 #define pii pair<int,int> 17 #define LL long long 18 namespace IO{ 19 char buf[1<<15],*fs,*ft; 20 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 21 int read(){ 22 int ch=gc(),f=0,x=0; 23 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 24 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 25 return f?-x:x; 26 } 27 }using namespace IO; 28 const int maxn=2020,N=2000; 29 int c[maxn][maxn]; 30 int sum[maxn][maxn]; 31 int T,k,n,m; 32 int main(){ 33 //freopen(FILE".in","r",stdin); 34 //freopen(FILE".out","w",stdout); 35 T=read(),k=read(); 36 c[0][0]=1; 37 up(i,1,N){ 38 c[i][0]=1; 39 up(j,1,i){ 40 c[i][j]=(c[i-1][j-1]+c[i-1][j])%k; 41 sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(c[i][j]==0?1:0); 42 } 43 up(j,i+1,N)sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; 44 } 45 while(T--){ 46 n=read(),m=read(); 47 if(m>n)m=n; 48 printf("%d\n",sum[n][m]); 49 } 50 return 0; 51 }
T2:
数学题目,需要证一下单调性(求个导如何?)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 using namespace std; 14 #define FILE "earthworm" 15 #define up(i,j,n) for(int i=(j);i<=(n);i++) 16 #define pii pair<int,int> 17 #define LL long long 18 namespace IO{ 19 char buf[1<<15],*fs,*ft; 20 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 21 int read(){ 22 int ch=gc(),f=0,x=0; 23 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 24 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 25 return f?-x:x; 26 } 27 }using namespace IO; 28 const int maxn=8001000; 29 const double E=0.0000001; 30 int a[maxn],b[maxn],c[maxn]; 31 int ha,hb,hc,tb=1,tc=1; 32 int n,m,u,v,t,q,d; 33 LL pop(){ 34 int L; 35 if(ha&&(a[ha]>=b[tb]||tb>hb)&&(a[ha]>=c[tc]||tc>hc))L=a[ha],ha--; 36 else if(tb<=hb&&(b[tb]>=a[ha]||!ha)&&(b[tb]>=c[tc]||tc>hc))L=b[tb],tb++; 37 else L=c[tc],tc++; 38 return L; 39 } 40 int main(){ 41 n=read(),m=read(),q=read(),u=read(),v=read(),t=read(); 42 up(i,1,n)a[i]=read(); 43 sort(a+1,a+n+1); 44 ha=n; 45 LL L,top=1; 46 up(i,1,m){ 47 L=pop()+d; 48 d+=q; 49 if(top*t==i){printf("%lld ",L);top++;} 50 b[++hb]=(int)(L*u/v)-d; 51 c[++hc]=L-b[hb]-2*d; 52 } 53 cout<<endl; 54 top=1; 55 up(i,1,m+n){ 56 L=pop(); 57 if(t*top==i){printf("%lld ",L+d);top++;} 58 } 59 return 0; 60 } 61
T3:
惭愧惭愧,考场不假思索,先打暴力......
后改记忆化,本质上都是状压dp;
吐槽的是,我同学写正解都被卡了一个n,而我写dfs,没有被卡掉......
实质上dfs会避免访问很多不可能出现的状态,所以效率比较高;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<ctime> 7 #include<cmath> 8 #include<set> 9 #include<map> 10 #include<queue> 11 #include<algorithm> 12 #include<iomanip> 13 using namespace std; 14 #define FILE "angrybirds" 15 #define up(i,j,n) for(int i=(j);i<=(n);i++) 16 #define pii pair<int,int> 17 #define LL long long 18 #define pdd pair<double,double> 19 namespace IO{ 20 char buf[1<<15],*fs,*ft; 21 int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} 22 int read(){ 23 int ch=gc(),f=0,x=0; 24 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();} 25 while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();} 26 return f?-x:x; 27 } 28 }using namespace IO; 29 inline bool chkmin(int &a,int b){return a>b?a=b,true:false;} 30 inline bool chkmax(int &a,int b){return a<b?a=b,true:false;} 31 const int maxn=20,N=2000; 32 const double E=0.00000001; 33 int T,n,m; 34 int ans; 35 double x[maxn],y[maxn]; 36 inline bool c(double x,double y){return abs(x-y)<=E;} 37 inline pdd slove(double q,double w,double e,double r){ 38 pdd dui; 39 if(c(q,e))return make_pair(0,0); 40 dui.first=(w*e-q*r)/(q*e*(q-e)); 41 if(dui.first+E>=0)return make_pair(0,0); 42 dui.second=(w*e-dui.first*q*q*e)/(q*e); 43 return dui; 44 } 45 int f[300000]; 46 int dfs(int top,int vis){ 47 if(f[vis]!=-1)return f[vis]; 48 if(top==n+1)return f[vis]=0; 49 if((1<<top-1)&vis)return f[vis]=dfs(top+1,vis); 50 pdd p; 51 f[vis]=n; 52 int q=vis; 53 up(i,top+1,n){ 54 vis=q; 55 if(!((1<<i-1)&vis)){ 56 p=slove(x[top],y[top],x[i],y[i]); 57 if(!p.first)continue; 58 vis=vis^(1<<top-1); 59 vis=vis^(1<<i-1); 60 up(j,top+1,n){ 61 if(vis&(1<<j-1))continue; 62 if(c(p.first*x[j]*x[j]+p.second*x[j],y[j]))vis=vis^(1<<j-1); 63 } 64 chkmin(f[q],dfs(top+1,vis)+1); 65 } 66 } 67 vis=q; 68 chkmin(f[vis],dfs(top+1,vis^(1<<top-1))+1); 69 return f[vis]; 70 } 71 int main(){ 72 //freopen(FILE".in","r",stdin); 73 //freopen(FILE".out","w",stdout); 74 scanf("%d",&T); 75 while(T--){ 76 scanf("%d%d",&n,&m); 77 up(i,1,n)scanf("%lf%lf",&x[i],&y[i]); 78 if(!m||m==2)ans=n; 79 if(m==1)ans=(n%3)?(n/3+2):(n/3+1); 80 memset(f,-1,sizeof(f)); 81 cout<<dfs(1,0)<<endl; 82 } 83 return 0; 84 }