• 9.10 模拟赛


    模拟赛第二弹,这次做的好多了~

    T1 

    题意就是给一棵树,求点对之间的距离

    因为n非常小(<1000),所以直接暴力bfs.....

    然而我为了锻炼手速 其实是没看数据 打了树剖【雾】

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 struct edge{
      7     int to,w,next;
      8 }e[2010];
      9 int n,q,times=1,first[1010],fa[1010],son[1010],size[1010],dep[1010];
     10 int wei[1010],belong[1010],pos[510][1010],lian[1010],top[1010];
     11 int a[1010][8010],nb[510],len[1010];
     12 bool vis[1010];
     13 void dfs1(int k,int f,int weight){
     14     int i,u,maxn=0,tmp=0;
     15     fa[k]=f;vis[k]=1;dep[k]=dep[f]+1;size[k]=1;
     16     len[k]=weight;
     17     for(i=first[k];~i;i=e[i].next){
     18         u=e[i].to;
     19         if(!vis[u]){
     20             dfs1(u,k,e[i].w);
     21             size[k]+=size[u];
     22             if(size[u]>maxn){
     23                 maxn=size[u];tmp=u;
     24             }
     25         }
     26     }
     27     son[k]=tmp;
     28     return;
     29 }
     30 void dfs2(int k,int t,int cnt){
     31     int i,u;nb[times]++;
     32     belong[k]=times;pos[times][cnt]=k;wei[k]=cnt;lian[k]=lian[fa[t]]+1;
     33     vis[k]=1;top[k]=t;
     34     if(son[k]){
     35         dfs2(son[k],t,cnt+1);
     36     }
     37     for(i=first[k];~i;i=e[i].next){
     38         u=e[i].to;
     39         if(!vis[u]){
     40             ++times;
     41             dfs2(u,u,1);
     42         }
     43     }
     44 }
     45 void build(int l,int r,int num,int t){
     46     if(l==r){
     47         a[t][num]=len[pos[t][l]];return;
     48     }
     49     int mid=(l+r)>>1;
     50     build(l,mid,num<<1,t);build(mid+1,r,(num<<1)+1,t);
     51     a[t][num]=a[t][num<<1]+a[t][(num<<1)+1];
     52     return;
     53 }
     54 int find(int ql,int qr,int l,int r,int num,int t){
     55     if(qr<l||ql>r) return 0;
     56     if(l>=ql&&r<=qr) return a[t][num];
     57     int mid=(l+r)>>1,re=0;
     58     if(mid>=ql) re+=find(ql,qr,l,mid,num<<1,t);
     59     if(mid<qr) re+=find(ql,qr,mid+1,r,(num<<1)+1,t);
     60     return re;
     61 }
     62 void swap(int &x,int &y){
     63     x^=y;y^=x;x^=y;
     64 }
     65 int query(int l,int r){
     66     int re=0;
     67     if(lian[l]>lian[r]) swap(l,r);
     68     while(lian[r]!=lian[l]){
     69         re+=find(wei[top[r]],wei[r],1,nb[belong[r]],1,belong[r]);
     70         r=fa[top[r]];
     71     }
     72     while(top[l]!=top[r]){
     73         re+=find(wei[top[l]],wei[l],1,nb[belong[l]],1,belong[l]);
     74         l=fa[top[l]];
     75         re+=find(wei[top[r]],wei[r],1,nb[belong[r]],1,belong[r]);
     76         r=fa[top[r]];
     77     }
     78     if(l==r) return re;
     79     if(dep[l]>dep[r]) swap(l,r);
     80     return re+find(wei[l],wei[r],1,nb[belong[l]],1,belong[l])-len[l];
     81 }
     82 int main(){
     83     freopen("pwalk.in","r",stdin);
     84     freopen("pwalk.out","w",stdout);
     85     int i,t1,t2,t3;
     86     memset(first,-1,sizeof(first));
     87     scanf("%d%d",&n,&q);
     88     for(i=1;i<n;i++){
     89         scanf("%d%d%d",&t1,&t2,&t3);
     90         e[i*2-1].to=t2;e[i*2-1].w=t3;e[i*2-1].next=first[t1];first[t1]=i*2-1;
     91         e[i*2].to=t1;e[i*2].w=t3;e[i*2].next=first[t2];first[t2]=i*2;
     92     }
     93     memset(vis,0,sizeof(vis));
     94     dfs1(1,1,0);
     95     memset(vis,0,sizeof(vis));
     96     dfs2(1,1,1);
     97     for(i=1;i<=times;i++) build(1,nb[i],1,i);
     98     for(i=1;i<=q;i++){
     99         scanf("%d%d",&t1,&t2);
    100         printf("%d
    ",query(t1,t2));
    101     }
    102 }

    T2

    题意:有一个n*m的池子,每个格子有四种状态:0水面,1石头,2荷叶,3荷叶并且是出发点,4荷叶并且是目的地

    每次能跳一个“日”字,问在放最少的荷叶且的情况下有多少种放置方法

    思路:bfs,对于每个点标记f[i][j]为最少放置的荷叶数,num[i][j]为总步数,然后bfs,根据先 f 再更新um 的方法。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #define inf 0x7fffffff
     9 #define ll long long
    10 using namespace std;
    11 inline int read()
    12 {
    13     int x=0,f=1;char ch=getchar();
    14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 struct node{
    19     int add,num,in;
    20 }a[50][50];
    21 const int dx[9]={0,1,1,-1,-1,2,2,-2,-2},dy[9]={0,2,-2,2,-2,1,-1,1,-1};
    22 int n,m,opx,opy,edx,edy;
    23 bool vis[50][50];
    24 void bfs(){
    25     queue<pair<int,int> >q;vis[opx][opy]=1;
    26     pair<int,int>t;
    27     t.first=opx;t.second=opy;
    28     q.push(t);
    29     int x,y,tx,ty,i,tmp;
    30     while(!q.empty()){
    31         t=q.front();q.pop();
    32         x=t.first;y=t.second;vis[x][y]=0;
    33 //        cout<<"bfs in "<<x<<ends<<y<<endl;
    34         for(i=1;i<=8;i++){
    35             tx=x+dx[i];ty=y+dy[i];
    36             if(tx>0&&tx<=n&&ty>0&&ty<=m&&a[tx][ty].in!=2){
    37                 tmp=(a[tx][ty].in==0);
    38                 t.first=tx;t.second=ty;
    39                 if(a[x][y].add+tmp<a[tx][ty].add){
    40 //                    cout<<"    type 1: going to "<<tx<<ends<<ty<<endl;
    41                     a[tx][ty].add=a[x][y].add+tmp;
    42                     a[tx][ty].num=a[x][y].num;
    43                     if(!vis[tx][ty]){
    44                         q.push(t);vis[tx][ty]=1;
    45                     }
    46                     continue;
    47                 }
    48                 if(a[x][y].add+tmp==a[tx][ty].add){
    49 //                    cout<<"    type 2: going to "<<tx<<ends<<ty<<endl;
    50                     a[tx][ty].num+=a[x][y].num;
    51                     if(!vis[tx][ty]){
    52                         q.push(t);vis[tx][ty]=1;
    53                     }
    54                     continue;
    55                 }
    56             }
    57         }
    58     }
    59 }
    60 int main(){
    61     int i,j;
    62     n=read();m=read();
    63     for(i=1;i<=n;i++){
    64         for(j=1;j<=m;j++){
    65             a[i][j].in=read();
    66             a[i][j].add=inf;
    67             if(a[i][j].in==3){
    68                 opx=i;opy=j;
    69                 a[i][j].add=0;a[i][j].num=1;
    70             }
    71             if(a[i][j].in==4){
    72                 edx=i;edy=j;
    73             }
    74         }
    75     }
    76     bfs();
    77     if(a[edx][edy].add==inf) printf("-1");
    78     else printf("%d
    %d",a[edx][edy].add,a[edx][edy].num);
    79 }
    80 /*
    81 
    82 4 5
    83 1 0 0 0 0
    84 3 0 0 0 0
    85 0 0 2 0 0
    86 0 0 0 4 0
    87 
    88 */

    T3:

    题意:有n个房间,q组询问,对于每一组询问,可能是入驻连续x个人,如果没有连续x个空房就跳过,也有可能是退一批房间(退掉的有可能是空的房间)

    一开始全是空房,对于每一个合理的入驻请求,输出连续x个房间中编号最小的那一个

    题解:看到连续房间和询问立马想到了线段树......然而比赛的时候似乎时间不够写挂了

    正解是用left,right和maxn标记每一个区间的左起连续空房、右起连续空房和最大空房数,每一次维护lazy的时候回溯处理加一步更新就好了

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 struct node{
     7     int l,r,x,y,len,lazy;
     8     node(){
     9         l=r=lazy=len=0;
    10     }
    11 }a[200100];
    12 void build(int l,int r,int num){
    13     a[num].l=l;a[num].r=r;
    14     a[num].x=a[num].y=a[num].len=r-l+1;
    15     int mid=(l+r)>>1;
    16     if(l!=r){
    17         build(l,mid,num<<1);build(mid+1,r,(num<<1)+1);
    18     }
    19 }
    20 void clear(int num){
    21     if(a[num].l==a[num].r||!a[num].lazy) return;
    22     int son=num<<1;
    23     if(a[num].lazy==2){
    24         a[son].x=a[son].y=a[son].len=a[son].r-a[son].l+1;
    25         a[son+1].x=a[son+1].y=a[son+1].len=a[son+1].r-a[son+1].l+1;
    26         a[son].lazy=a[son+1].lazy=1;
    27     }
    28     else{
    29         a[son].x=a[son].y=a[son].len=0;
    30         a[son+1].x=a[son+1].y=a[son+1].len=0;
    31         a[son].lazy=a[son+1].lazy=2;
    32     }
    33     a[num].lazy=0;
    34 }
    35 int find(int len,int num){
    36 //    cout<<"find "<<len<<ends<<num<<endl;
    37     int son=num<<1;
    38     clear(num);clear(son);clear(son+1);
    39     if(a[num].x>=len) return a[num].l;
    40     if(a[son].len>=len) return find(len,son);
    41     if(a[son].y+a[son+1].x>=len) return a[son].r-a[son].y+1;
    42     return find(len,son+1);
    43 }
    44 void update(int num){
    45 //    cout<<"update "<<num<<endl;
    46     int son=num<<1;
    47     clear(son);clear(son+1);
    48     a[num].x=((a[son].len==a[son].r-a[son].l+1)?a[son].x+a[son+1].x:a[son].x);
    49     a[num].y=((a[son+1].len==a[son+1].r-a[son+1].l+1)?a[son+1].y+a[son].y:a[son+1].y);
    50 //    cout<<a[num].len<<endl;
    51     a[num].len=max(a[son].len,a[son+1].len);
    52 //    cout<<a[num].len<<endl;
    53     a[num].len=max(a[num].len,a[son].y+a[son+1].x);
    54 //    cout<<a[num].len<<endl;
    55 }
    56 void checkin(int l,int r,int num){
    57     clear(num);
    58     if(a[num].l>r||a[num].r<l) return;
    59     if(a[num].l>=l&&a[num].r<=r){
    60         a[num].x=a[num].y=a[num].len=0;a[num].lazy=1;return;
    61     }
    62     int mid=(a[num].l+a[num].r)>>1,son=num<<1;
    63     if(mid>=l) checkin(l,r,son);
    64     if(mid<r) checkin(l,r,son+1);
    65     update(num);
    66 }
    67 void checkout(int l,int r,int num){
    68     clear(num);
    69     if(a[num].l>r||a[num].r<l) return;
    70     if(a[num].l>=l&&a[num].r<=r){
    71         a[num].x=a[num].y=a[num].len=a[num].r-a[num].l+1;a[num].lazy=2;return;
    72     }
    73     int mid=(a[num].l+a[num].r)>>1,son=num<<1;
    74     if(mid>=l) checkout(l,r,son);
    75     if(mid<r) checkout(l,r,son+1);
    76     update(num);
    77 }
    78 int n,m,ans;
    79 int main(){
    80     int i,t1,t2,t3;
    81     scanf("%d%d",&n,&m);
    82     build(1,n,1);
    83     for(i=1;i<=m;i++){
    84         scanf("%d",&t1);
    85         if(t1==1){
    86             scanf("%d",&t2);
    87             if(a[1].len<t2){
    88                 printf("0
    ");continue;
    89             }
    90             ans=find(t2,1);
    91             printf("%d
    ",ans);
    92             checkin(ans,ans+t2-1,1);
    93         }
    94         else{
    95             scanf("%d%d",&t2,&t3);
    96             checkout(t2,t2+t3-1,1);
    97         }
    98     }
    99 }

    T4:

    题意:有一个图求最小生成树,使得从某一个点出发,对于路上每经过一次的点加一次该点权值,通过的边也加一次权值,问怎样最小,输出最小值

    思路:kruskal,因为对于任何一个点来说,他有多少条出边就会加多少次该点的权值。

    因此输入的时候把每条边加上两端端点的权值,跑kruskal,最后再加上一个点权最小的点就好了(因为根据题意这个点多跑一遍)

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define ll long long
     5 using namespace std;
     6 struct erickin{
     7     int to,next,from,w;
     8 }a[200100];
     9 int n,m,wei[10010],first[10010];
    10 ll ans=0;
    11 int f[10010];
    12 bool cmp(erickin l,erickin r){
    13     return l.w<r.w;
    14 }
    15 int find(int k){
    16     return ((f[k]==k)?k:f[k]=find(f[k]));
    17 }
    18 void kruskal(){
    19     int i,times=0,fx,fy;
    20     for(i=1;i<=n;i++) f[i]=i;
    21     for(i=1;i<=m;i++){
    22         fx=find(a[i].from);fy=find(a[i].to);
    23         if(fx!=fy){
    24             f[fx]=fy;ans+=a[i].w;
    25             times++;
    26             if(times==n-1) break;
    27         }
    28     }
    29 }
    30 int main(){
    31     int i,t1,t2,t3;
    32     scanf("%d%d",&n,&m);
    33     for(i=1;i<=n;i++) scanf("%d",&wei[i]);
    34     for(i=1;i<=m;i++){
    35         scanf("%d%d%d",&t1,&t2,&t3);
    36         a[i].to=t2;a[i].from=t1;a[i].next=first[t1];first[t1]=i;a[i].w=t3*2+wei[t1]+wei[t2];
    37     }
    38 //    for(i=1;i<=m;i++) cout<<a[i].from<<ends<<a[i].to<<ends<<a[i].w<<endl;
    39     sort(a+1,a+m+1,cmp);
    40     sort(wei+1,wei+n+1);
    41     kruskal();
    42     printf("%lld",ans+wei[1]);
    43 }
    44 /*
    45 5 7
    46 10
    47 10
    48 20
    49 6
    50 30
    51 1 2 5
    52 2 3 5
    53 2 4 12
    54 3 4 17
    55 2 5 15
    56 3 5 6
    57 4 5 12
    58 */
  • 相关阅读:
    BOZJ2200: [Usaco2011 Jan]道路和航线
    poj3662
    网络流
    最短路
    约瑟夫环
    二分图匹配
    HDU 3938 Portal
    背包dp专题训练
    noip2013day1模拟赛
    2017.10.24:lca专题系列
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/7530657.html
Copyright © 2020-2023  润新知