• 【NOIP2013】提高组


    Day1

    T1转圈游戏

    题目链接

    很明显每进行n轮就一定会回到原来的位置,所以游戏只相当于进行了10k%n轮,所以会走到(x+10k%n)%n的位置。

    写个快速幂也就没了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 int ksm(long long x,int y,int p){
     4     int res=1;
     5     while(y){
     6         if(y&1)res=res*x%p;
     7         x=x*x%p;
     8         y>>=1;
     9     }
    10     return res;
    11 }
    12 int main(){
    13     int n,m,k,x;
    14     scanf("%d %d %d %d",&n,&m,&k,&x);
    15     printf("%d",(x+m*ksm(10,k,n)%n)%n);
    16     return 0;
    17 }
    D1 T1

    T2火柴排队

    题目链接

    因为代价是差的平方级所以一定要让极差尽可能小(类似与基本不等式什么的?),那么很容易想到就是把两个序列按从小到大排序,一一对应。

    那不就是求个逆序对吗=)-->移动两个序列的元素是等价的因此我们可以认定其中一个序列是有序的。

    用树状数组或归并排序都可以。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define lowbit(x) x&-x
     5 const int N=1e5+7,mod=99999997;
     6 struct node{
     7     int wi,id;
     8 }e[N],q[N];
     9 int n,pai[N],rank[N],to[N],tr[N];
    10 int read(){
    11     int ans=0,f=1;char c=getchar();
    12     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    13     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    14     return ans*f;
    15 }
    16 int ans=0;
    17 bool cmp(node aa,node bb){return aa.wi<bb.wi;}
    18 int sum(int x){
    19     long long ss=0;
    20     for(;x<=n;x+=lowbit(x))ss=(ss+tr[x])%mod;
    21     return ss;
    22 }
    23 void add(int x){
    24     for(;x;x-=lowbit(x))tr[x]++;
    25 }
    26 void ni(){
    27     for(int i=1;i<=n;i++){
    28         int ss=sum(rank[i]);
    29         ans=(ans+ss)%mod;
    30         add(rank[i]);
    31     }
    32 }
    33 int main(){
    34     n=read();
    35     for(int i=1,a;i<=n;i++)a=read(),e[i]=(node){a,i};
    36     std::sort(e+1,e+1+n,cmp);
    37     for(int i=1;i<=n;i++)pai[e[i].id]=i;
    38     for(int i=1;i<=n;i++)to[pai[i]]=i;
    39     for(int i=1,a;i<=n;i++)a=read(),q[i]=(node){a,i};
    40     std::sort(q+1,q+1+n,cmp);
    41     for(int i=1;i<=n;i++)rank[q[i].id]=to[i];
    42     ni();
    43     printf("%d",ans);
    44     return 0;
    45 }
    D1 T2

    T3货车运输

    题目链接

    既然是最大承重,当然就是先求一棵最大生成树辣><

    然后就在倍增预处理时记一下每个节点每次向上跳2i时经过路径的最小值;

    每次倍增求LCA时顺便取min就可以了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 const int M=5e4+10,N=1e4+7,inf=0x3f3f3f3f;
     6 struct node{
     7     int fr,to,w;
     8     bool operator <(const node&p)const {return p.w>w;}
     9 };
    10 struct no{int ne,to,w;}e[N*2];
    11 std::priority_queue<node>q;
    12 int n,m,fa[N],tot=0,first[N],deep[N];
    13 int mni[N][20],gr[N][20];
    14 int min(int x,int y){return x>y?y:x;}
    15 int read(){
    16     int ans=0,f=1;char c=getchar();
    17     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    18     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    19     return ans*f;
    20 }
    21 void ins(int u,int v,int w){
    22     e[++tot]=(no){first[u],v,w};first[u]=tot;
    23 }
    24 int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
    25 void dfs(int x,int ff){
    26     for(int i=1;(1<<i)<=deep[x];i++){
    27         gr[x][i]=gr[gr[x][i-1]][i-1];
    28         mni[x][i]=min(mni[x][i-1],mni[gr[x][i-1]][i-1]);
    29     }
    30     for(int i=first[x];i;i=e[i].ne){
    31         int to=e[i].to;
    32         if(to!=ff){
    33             deep[to]=deep[x]+1;
    34             gr[to][0]=x;mni[to][0]=e[i].w;
    35             dfs(to,x);
    36         }
    37     }
    38 }
    39 int lca(int x,int y){
    40     int mn=inf;
    41     if(deep[x]<deep[y])std::swap(x,y);
    42     int d=deep[x]-deep[y];
    43     for(int i=0;(1<<i)<=deep[x]&&i<=20;i++)
    44         if(d&(1<<i)){
    45             mn=min(mn,mni[x][i]);
    46             x=gr[x][i];
    47         }
    48     if(x==y)return mn;
    49     for(int i=20;i>=0;i--){
    50         if((1<<i)>deep[x]||gr[x][i]==gr[y][i])continue;
    51         mn=min(mn,mni[x][i]);mn=min(mn,mni[y][i]);
    52         x=gr[x][i];y=gr[y][i];
    53     }
    54     if(!gr[x][0])return -1;
    55     mn=min(mn,min(mni[x][0],mni[y][0]));
    56     return mn;
    57 }
    58 int main(){
    59     n=read();m=read();
    60     for(int i=1,a,b,c;i<=m;i++){
    61         a=read();b=read();c=read();
    62         q.push((node){a,b,c});
    63     }
    64     for(int i=1;i<=n;i++)fa[i]=i;
    65     while(!q.empty()){
    66         node p=q.top();q.pop();
    67         int f1=getf(p.fr),f2=getf(p.to);
    68         if(f1!=f2){
    69             ins(p.fr,p.to,p.w);ins(p.to,p.fr,p.w);
    70             fa[f1]=f2;
    71         }
    72     }
    73     dfs(1,0);
    74     int qu=read();
    75     while(qu--){
    76         int x=read(),y=read();
    77         int mn=lca(x,y);
    78         printf("%d
    ",mn);
    79     }
    80     return 0;
    81 }
    D1 T3

    Day2

    T1积木大赛

    题目链接

    如果当前块比前一块高,说明需要多用hi[i]-hi[i-1]次。没了......

     1 #include<cstdio>
     2 #include<algorithm>
     3 int main(){
     4     int n,x,last=0,ans=0;
     5     scanf("%d",&n);
     6     for(int i=1;i<=n;i++){
     7         scanf("%d",&x);
     8         if(x>last)ans+=x-last;
     9         last=x;
    10     }
    11     printf("%d",ans);
    12     return 0;
    13 }
    D2 T1

    T2花匠

    题目链接

    求一下拐点数再+2,也解决了......

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 const int N=1e5+10;
     5 int n,hi[N],tt;
     6 int read(){
     7     int ans=0,f=1;char c=getchar();
     8     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     9     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    10     return ans*f;
    11 }
    12 int main(){
    13     n=read();
    14     for(int i=1;i<=n;i++)hi[i]=read();
    15     if(n==1)return printf("1"),0;
    16     int t=2;
    17     while(t<=n&&hi[t]==hi[t-1])t++;
    18     if(hi[t]>hi[t-1])tt=1;
    19     else tt=0;
    20     int sum=1;
    21     for(int i=t+1;i<=n;i++){
    22         if(hi[i]==hi[i-1])continue;
    23         if(hi[i]>hi[i-1]&&!tt){
    24             sum++;tt^=1;
    25         }
    26         else if(hi[i]<hi[i-1]&&tt){
    27             sum++;tt^=1;
    28         }
    29     }
    30     sum++;
    31     printf("%d",sum);
    32     return 0;
    33 }
    D2 T2

    T3华容道

    题目链接

    超超超超级恶心的预处理......

    显然完成游戏是要先把白格子移到起点格子的四周,再用白格为起点格子铺路。

    那么我们这里就需要求白格子铺路的代价,好在这题地图是确定的,因此我们可以先预处理出每个格子(当然是可移动的)四周的格子在不经过它本身的前提下互相到达的代价(bfs)。

    最后跑一个带方向的SPFA-->预处理时也要记得记录是从哪个方向走到当前格子的。

    最后还是看代码吧,写了一些注释......

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<cmath>
      6 #define mem(a,p) memset(a,p,sizeof(a))
      7 const int N=35,inf=0x3f3f3f3f;
      8 int n,m,q,h1,t1,h2,t2,ex,ey,sx,sy,tx,ty;
      9 int mp[N][N],cc[6][2]={{0,0},{0,1},{1,0},{-1,0},{0,-1}};
     10 int der[6]={0,4,3,2,1},step[N][N][6][6],dis[N][N][6];
     11 //der[k]存k的反方向,防止走回去导致死循 
     12 //dis[x][y][i]表示起始点从i方向走到(x,y)这个点的最小代价 
     13 bool ok[N][N];
     14 struct no{
     15     int x,y,st,k;
     16 }q1[4000005],q2[4000005];//q1、q2分别是用于bfs和SPFA的队列 
     17 int min(int x,int y){return x>y?y:x;}
     18 int read(){
     19     int ans=0,f=1;char c=getchar();
     20     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     21     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
     22     return ans*f;
     23 }
     24 void pre(int x,int y){
     25     for(int i=1;i<=4;i++){
     26         if(!mp[x+cc[i][0]][y+cc[i][1]])continue;
     27         for(int j=1;j<=4;j++){//mp[x][y]四个方向的格子(可移动的)两两相互到达所需代价 
     28             int ax=x+cc[i][0],ay=y+cc[i][1];
     29             if(i==j||step[x][y][i][j])continue;
     30             int px=x+cc[j][0],py=y+cc[j][1];
     31             if(!mp[px][py])continue;
     32             h1=1;t1=0;
     33             mem(ok,0);
     34             q1[++t1]=(no){ax,ay,0,i};
     35             ok[ax][ay]=1;
     36             int ans=-1;
     37             while(h1<=t1){
     38                 no p=q1[h1];h1++;
     39                 if(p.x==px&&p.y==py){ans=p.st;break;}
     40                 for(int k=1;k<=4;k++){
     41                     int bx=p.x+cc[k][0],by=p.y+cc[k][1];
     42                     if(k==der[p.k]||!mp[bx][by]||ok[bx][by]||(bx==x&&by==y))continue;//bfs
     43                     q1[++t1]=(no){bx,by,p.st+1,k};
     44                     ok[bx][by]=1;
     45                 }
     46             }
     47             step[x][y][i][j]=step[x][y][j][i]=ans;
     48         }
     49     }
     50 }
     51 void pre_white(){//预处理白格子走到起始格子四周的代价 
     52     h2=1;t2=0;
     53     for(int i=1;i<=4;i++){
     54         if(!mp[sx+cc[i][0]][sy+cc[i][1]])continue;
     55         mem(ok,0);h1=1;t1=0;
     56         int px=sx+cc[i][0],py=sy+cc[i][1];
     57         q1[++t1]=(no){ex,ey,0,0};ok[ex][ey]=1;
     58         int ans=inf;
     59         while(h1<=t1){
     60             no p=q1[h1];h1++;
     61             if(p.x==px&&p.y==py){
     62                 ans=p.st;
     63                 if(ans<inf){
     64                     q2[++t2]=(no){px,py,ans+1,i};
     65                     dis[px][py][i]=ans+1;
     66                 }break;
     67             }
     68             for(int k=1;k<=4;k++){
     69                 int bx=p.x+cc[k][0],by=p.y+cc[k][1];
     70                 if(k==der[p.k]||!mp[bx][by]||ok[bx][by]||(bx==sx&&by==sy))continue;
     71                 q1[++t1]=(no){bx,by,p.st+1,k};
     72                 ok[bx][by]=1;
     73             }
     74         }
     75     }
     76 } 
     77 void solve(){
     78     for(int i=1;i<=n;i++)
     79         for(int j=1;j<=m;j++)
     80             for(int k=1;k<=4;k++)
     81             dis[i][j][k]=inf;
     82     pre_white();
     83     int ans=inf;
     84     while(h2<=t2){
     85         no p=q2[h2++];
     86         if(dis[p.x][p.y][p.k]!=p.st)continue;
     87         if(p.x==tx&&p.y==ty){
     88             ans=min(ans,p.st);
     89             continue;
     90         }
     91         for(int k=1;k<=4;k++){
     92             int bx=p.x+cc[k][0],by=p.y+cc[k][1];
     93             if(k==der[p.k]||!mp[bx][by])continue;
     94             int wi=step[p.x][p.y][der[p.k]][k];
     95             if(wi<=0)continue;//说明此格子走不过来 
     96             if(dis[bx][by][k]>dis[p.x][p.y][p.k]+wi+1){//带方向变量的SPFA
     97                 dis[bx][by][k]=dis[p.x][p.y][p.k]+wi+1;
     98                 q2[++t2]=(no){bx,by,dis[bx][by][k],k};
     99             }
    100         }
    101     }
    102     if(ans>=inf||ans<=0)printf("-1
    ");
    103     else printf("%d
    ",ans);
    104 }
    105 int main(){ 
    106     n=read();m=read();q=read();
    107     for(int i=1;i<=n;i++)
    108         for(int j=1;j<=m;j++)
    109         mp[i][j]=read();
    110         for(int i=1;i<=n;i++)
    111             for(int j=1;j<=m;j++)
    112             if(mp[i][j])pre(i,j);
    113     while(q--){
    114         ex=read();ey=read();sx=read();sy=read();tx=read();ty=read();
    115         if(sx==tx&&sy==ty)printf("0
    ");//记得特判...... 
    116         else solve();
    117     }
    118     return 0;
    119 }
    D2 T3
  • 相关阅读:
    【转帖】asp.net mvc与webform区别
    [学习jquery]深入了解jquery(1)jquery对象
    windows ce 4.2/5.0/6.0/windows mobile设备直接连接PC端的SQLserver
    dotNet dispose 和 close的区别
    简易快速理解 ERP
    互联网盈利模式77种创新 [转]
    软件开发的基础知识[1]
    什么是 SHTML
    ASP.NET 2.0:弃用 DataGrid 吧,有新的网格控件了![msdn]
    主页制作五十式[好帖就要转]
  • 原文地址:https://www.cnblogs.com/JKAI/p/7791477.html
Copyright © 2020-2023  润新知