[NOIP补坑计划]NOIP2013 题解&做题心得

场上预计得分:100+100+100+100+100+60=560(省一分数线410)

五道傻逼题+一道大搜索题……

题解:

D1T1 转圈游戏

题面

水题送温暖~

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 typedef long long ll;
11 int n,m,k,x,p,num;
12 int ksm(int x,int y,int p){
13     int ret=1;
14     for(;y;y>>=1,x=(ll)x*x%p){
15         if(y&1)ret=(ll)ret*x%p;
16     }
17     return ret;
18 }
19 int main(){
20     scanf("%d%d%d%d",&n,&m,&k,&x);
21     printf("%d",((ll)m*ksm(10,k,n)%n+x)%n);
22     return 0;
23 }

D1T2 火柴排队

题面

怎么感觉比D1T3还难啊……总是在想DP和贪心结果SB线段树就没了……

显然最优配对是分别排序后对应的数,求出对应位置直接求逆序对即可。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 #define mod 99999997;
10 using namespace std;
11 typedef long long ll;
12 struct node{
13     int x,id;
14     friend bool operator <(node a,node b){
15         return a.x<b.x;
16     }
17 }aa[100001],bb[100001];
18 int n,x,a[100001],b[100001],s[100001];
19 ll ans=0,t[500001];
20 void updata(int l,int r,int u,int p){
21     t[u]++;
22     if(l==r)return;
23     int mid=(l+r)/2;
24     if(p<=mid)updata(l,mid,u*2,p);
25     else updata(mid+1,r,u*2+1,p);
26 }
27 int query(int l,int r,int u,int L,int R){
28     if(L<=l&&r<=R){
29         return t[u];
30     }
31     int mid=(l+r)/2,ret=0;
32     if(L<=mid)ret+=query(l,mid,u*2,L,R);
33     if(mid<R)ret+=query(mid+1,r,u*2+1,L,R);
34     return ret;
35 }
36 int main(){
37     scanf("%d",&n);
38     for(int i=1;i<=n;i++){
39         scanf("%d",&a[i]);
40         aa[i].x=a[i];
41         aa[i].id=i;
42     }
43     for(int i=1;i<=n;i++){
44         scanf("%d",&b[i]);
45         bb[i].x=b[i];
46         bb[i].id=i;
47     }
48     sort(aa+1,aa+n+1);
49     sort(bb+1,bb+n+1);
50     for(int i=1;i<=n;i++){
51         s[aa[i].id]=bb[i].id;
52     }
53     for(int i=1;i<=n;i++){
54         ans=(ans+s[i]-query(1,n,1,1,s[i])-1)%mod;
55         updata(1,n,1,s[i]);
56     }
57     printf("%d",ans);
58     return 0;
59 }

D1T3 火车运输

题面

傻逼题,在最大生成树上跑树上倍增即可。

(我AKDay1啦!)

 

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 typedef long long ll;
11 struct edge{
12     int v,w,next;
13 }a[100001];
14 struct _edge{
15     int u,v,w;
16     friend bool operator <(_edge a,_edge b){
17         return a.w>b.w;
18     }
19 }e[50001];
20 int n,m,u,v,tot=0,head[10001],dep[10001],fa[10001],f[10001][15],mi[10001][15];
21 bool used[10001];
22 int ff(int u){
23     return fa[u]==u?u:fa[u]=ff(fa[u]);
24 }
25 void add(int u,int v,int w){
26     a[++tot].v=v;
27     a[tot].w=w;
28     a[tot].next=head[u];
29     head[u]=tot;
30 }
31 void dfs(int u,int ff,int dpt,int minn){
32     used[u]=true;
33     dep[u]=dpt;
34     f[u][0]=ff;
35     mi[u][0]=minn;
36     for(int i=1;i<=14;i++){
37         f[u][i]=f[f[u][i-1]][i-1];
38         mi[u][i]=min(mi[u][i-1],mi[f[u][i-1]][i-1]);
39     }
40     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
41         int v=a[tmp].v;
42         if(v!=ff){
43             dfs(v,u,dpt+1,a[tmp].w);
44         }
45     }
46 }
47 int work(int u,int v){
48     if(dep[u]<dep[v])swap(u,v);
49     int ret=inf,l=dep[u]-dep[v];
50     for(int i=14;i>=0;i--){
51         if((1<<i)&l){
52             ret=min(ret,mi[u][i]);
53             u=f[u][i];
54         }
55     }
56     if(u==v)return ret;
57     for(int i=14;i>=0;i--){
58         if(f[u][i]!=f[v][i]){
59             ret=min(ret,min(mi[u][i],mi[v][i]));
60             u=f[u][i],v=f[v][i];
61         }
62     }
63     return min(ret,min(mi[u][0],mi[v][0]));
64 }
65 int main(){
66     memset(head,-1,sizeof(head));
67     scanf("%d%d",&n,&m);
68     for(int i=1;i<=n;i++)fa[i]=i;
69     for(int i=1;i<=m;i++){
70         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
71     }
72     sort(e+1,e+m+1);
73     for(int i=1;i<=m;i++){
74         int u=e[i].u,v=e[i].v,fu=ff(u),fv=ff(v);
75         if(fu!=fv){
76             add(u,v,e[i].w);
77             add(v,u,e[i].w);
78             fa[fu]=fv;
79         }
80     }
81     for(int i=1;i<=n;i++){
82         if(!used[i])dfs(i,0,0,inf);
83     }
84     scanf("%d",&m);
85     for(int i=1;i<=m;i++){
86         scanf("%d%d",&u,&v);
87         printf("%d\n",(ff(u)==ff(v))?work(u,v):-1);
88     }
89     return 0;
90 }

 

D2T1 积木大赛

题面

水题送温暖~

ps:此题同NOIP2018D1T1铺设道路

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 typedef long long ll;
11 int n,x,las=0,ans=0;
12 int main(){
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++){
15         scanf("%d",&x);
16         if(x>las)ans+=x-las;
17         las=x;
18     }
19     printf("%d",ans);
20     return 0;
21 }

D2T2 花匠

题面

这是D2T2????(原数据范围$10^5$,LOJ加到了$2\times 10^6$)

结论是移一位两种情况就互换了

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 typedef long long ll;
11 int n,x,h0,ans1=1,ans2=1;
12 int main(){
13     scanf("%d%d",&n,&h0);
14     for(int i=2;i<=n;i++){
15         scanf("%d",&x);
16         if(x>h0)ans1=max(ans1,ans2+1);
17         if(x<h0)ans2=max(ans2,ans1+1);
18         h0=x;
19     }
20     printf("%d",max(ans1,ans2));
21     return 0;
22 }

D2T3 华容道

题面

可能其他题的难度全集中到这题来了?太久没做过搜索题了,场上$O(qn^4)$60分暴力滚粗;

正解就是预处理每一格向四个方向走的距离然后每次询问做spfa……

 

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<queue>
  7 #define inf 0x7f7f7f7f
  8 #define eps 1e-9
  9 #define DCSB {puts("-1");return;}
 10 using namespace std;
 11 typedef long long ll;
 12 const int way[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
 13 struct node{
 14     int x,y,w;
 15     node(int _x=0,int _y=0,int _w=0){
 16         x=_x,y=_y,w=_w;
 17     }
 18 };
 19 int n,m,q,ans,ex,ey,sx,sy,tx,ty,f[31][31][4],dis[31][31],mp[31][31],go[31][31][4][4];
 20 bool isin[31][31][4];
 21 bool chk(int x,int y){
 22     return x<1||x>n||y<1||y>m||!mp[x][y];
 23 }
 24 int bfs(int sx,int sy,int tx,int ty){
 25     if(!mp[sx][sy]||!mp[tx][ty])return inf;
 26     queue<node>q;
 27     memset(dis,0x7f,sizeof(dis));
 28     dis[sx][sy]=0;
 29     q.push((node){sx,sy,0});
 30     while(!q.empty()){
 31         node u=q.front();
 32         q.pop();
 33         if(u.x==tx&&u.y==ty)return dis[tx][ty];
 34         for(int k=0;k<4;k++){
 35             int xx=u.x+way[k][0],yy=u.y+way[k][1];
 36             if(chk(xx,yy)||dis[xx][yy]!=inf)continue;
 37             dis[xx][yy]=dis[u.x][u.y]+1;
 38             q.push((node){xx,yy,0});
 39         }
 40     }
 41     return inf;
 42 }
 43 void _(){
 44     for(int i=1;i<=n;i++){
 45         for(int j=1;j<=m;j++){
 46             int ch=mp[i][j];
 47             mp[i][j]=0;
 48             for(int k=0;k<4;k++){
 49                 for(int l=0;l<4;l++){
 50                     go[i][j][k][l]=bfs(i+way[k][0],j+way[k][1],i+way[l][0],j+way[l][1]);
 51                 }
 52             }
 53             mp[i][j]=ch;
 54         }
 55     }
 56 }
 57 void spfa(){
 58     queue<node>q;
 59     memset(isin,0,sizeof(isin));
 60     for(int k=0;k<4;k++){
 61         if(f[sx][sy][k]!=inf){
 62             q.push((node){sx,sy,k});
 63             isin[sx][sy][k]=true;
 64         }
 65     }
 66     while(!q.empty()){
 67         node u=q.front();
 68         q.pop();
 69         int x=u.x,y=u.y,w=u.w;
 70         isin[x][y][w]=false;
 71         for(int k=0;k<4;k++){
 72             int xx=x+way[k][0],yy=y+way[k][1];
 73             if(chk(xx,yy)||go[x][y][w][k]==inf)continue;
 74             if(f[xx][yy][k^1]>f[x][y][w]+go[x][y][w][k]+1){
 75                 f[xx][yy][k^1]=f[x][y][w]+go[x][y][w][k]+1;
 76                 if(!isin[xx][yy][k^1]){
 77                     q.push((node){xx,yy,k^1});
 78                     isin[xx][yy][k^1]=true;
 79                 }
 80             }
 81         }
 82     }
 83 }
 84 void work(){
 85     if(sx==tx&&sy==ty){
 86         puts("0");
 87         return;
 88     }
 89     if((sx==ex&&sy==ey)||chk(sx,sy)||chk(tx,ty)||chk(ex,ey))DCSB;
 90     memset(f,0x7f,sizeof(f));
 91     mp[sx][sy]=0;
 92     for(int k=0;k<4;k++){
 93         f[sx][sy][k]=bfs(ex,ey,sx+way[k][0],sy+way[k][1]);
 94     }
 95     mp[sx][sy]=1;
 96     spfa();
 97     ans=inf;
 98     for(int k=0;k<4;k++){
 99         ans=min(ans,f[tx][ty][k]);
100     }
101     printf("%d\n",ans==inf?-1:ans);
102 }
103 int main(){
104     scanf("%d%d%d",&n,&m,&q);
105     for(int i=1;i<=n;i++){
106         for(int j=1;j<=m;j++){
107             scanf("%d",&mp[i][j]);
108         }
109     }
110     _();
111     /*for(int i=1;i<=n;i++){
112         for(int j=1;j<=m;j++){
113             for(int k=0;k<4;k++){
114                 for(int l=0;l<4;l++){
115                     printf("%d ",go[i][j][k][l]);
116                 }
117             }
118             puts("");
119         }
120         puts("");
121     }*/
122     for(int i=1;i<=q;i++){
123         scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
124         work();
125     }
126     return 0;
127 }

 

总结:

1.两个小时干完五题然后发呆,D1一小时写完,D2前两题加起来800B……就D2T3有点代码量;

2.搜索姿势水平要提高。

 

posted @ 2018-10-27 20:22  DCDCBigBig  阅读(275)  评论(2编辑  收藏  举报