zoukankan      html  css  js  c++  java
  • 模拟13 题解

    T1[A. 矩阵游戏]

    40%算法

    首先注意几个性质:先乘后乘,或有没有0都一样,

    记录下每一行,每一列乘的累计值$a_i b_j$

    最后$ans=cal(i,j)*a_i*b_j$  其中cal为O(1)计算初始每个位置的值$O(nm)$枚举

    100%算法

    只需要把式子展开,然后就能分别O(n)O(m)计算

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #define R register
     6 #define int long long
     7 using namespace std;
     8 int read()
     9 {
    10     int f=1,x=0;char ch=getchar();
    11     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    13     return f*x;
    14 }
    15 const int maxn=1000005;
    16 const int mod=1e9+7;
    17 int n,m,k;
    18 int a[maxn],b[maxn];
    19 int fa[maxn],fb[maxn];
    20 char opt[3];
    21 int cal(int x,int y)
    22 {
    23     return ((x-1)*m%mod+y)%mod;
    24 }
    25 signed  main()
    26 {
    27 //    freopen("data","r",stdin);
    28     n=read(),m=read(),k=read();
    29     for(int i=1;i<=n;i++)
    30         fa[i]=1;
    31     for(int i=1;i<=m;i++)
    32         fb[i]=1;
    33     while(k--)
    34     {
    35         scanf("%s",opt);
    36         R int x=read(),y=read();
    37         if(opt[0]=='R')
    38         {
    39             fa[x]=fa[x]*y%mod;
    40         }
    41         else 
    42         {
    43             fb[x]=fb[x]*y%mod;
    44         }
    45     }
    46     int sum=0,dtb=0,ta=0;
    47     for(int i=1;i<=n;i++){
    48         ta=(ta+(i-1)*m%mod*fa[i]%mod)%mod;
    49         dtb=(dtb+fa[i])%mod;
    50     }
    51     for(int j=1;j<=m;j++)
    52         (sum+=fb[j]*ta%mod+j*fb[j]%mod*dtb%mod)%=mod;;
    53     printf("%lld
    ",sum%mod);
    54 }
    View Code

    T2[B. 跳房子]「模拟」

    20%算法

    傻模拟,别预处理,否则改的挺麻烦的,

     80%算法

    记录一下每一列的上一次经过时的横坐标,当与这一次访问的横坐标相等时,证明这构成了一个以m为一个循环长度的循环解,

    将k取模,省得暴力走完,就能求出答案,修改时暴力修改

    100%算法

    记录第一列的每个点走m步之后到了第一列的某点jump[i]

    然后不断跳,直到找到一个走过的点,然后记录一下这其中的走的步数,用k减去

    修改:除了修改每个点本身的值,还要修改这个点所影响的第一列的一个范围,

    容易发现,这会形成一个区间,只要找到这个区间的上下边界,

    y--的同时,分别看上下边界能否扩展,若其一不能扩展或缩小至下边界高于上边界,return就行,不会对jump有影响

    那么有没有可能这个return的这个边界的另一条可行道路接着走不会return呢?

    显然是不可能的,,手模一下,,一个边界无法扩展的条件只有上下两个边界紧挨着时

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<string>
      6 #define R register
      7 #define INF 0x7fffffff
      8 using namespace std;
      9 inline int read(){
     10     R int f=1,x=0;char ch=getchar();
     11     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     13     return f*x;
     14 }
     15 int n,m,a[2100][2100],v[2100],jump[2005];// v[i] whether irow has been arrived
     16 int vk[2100];//when is irow arrived
     17 int fx(int x){return ((x-1)%n+n)%n+1;}
     18 int fy(int y){return ((y-1)%m+m)%m+1;}
     19 inline int mov(int x,int y)//go ahead
     20 {
     21     R int nxt=-1,mx=-1;
     22     for(R int i=x-1;i<=x+1;++i){
     23         R int da=a[fx(i)][fy(y+1)];
     24         if(da>mx){
     25             mx=da;
     26             nxt=i;    
     27         }
     28     }
     29     return nxt;
     30 }
     31 inline int mof(int x,int y)//from (x,y) to (x',1)
     32 {
     33     do{
     34         x=fx(mov(x,y));
     35         y++;
     36     }while(y<=m);
     37     return x;
     38 }
     39 inline void update(int x,int y)
     40 {
     41     const int tx=mof(x,y);
     42     int low=x,high=x,yy=y;
     43     while(yy!=1)
     44     {
     45         --yy;
     46         int lo=INF,hi=-INF;
     47         for(int i=low-1;i<=low+1;i++){
     48             int nxx=mov(i,yy);
     49             if(nxx<=high&&nxx>=low){
     50                 lo=i;
     51                 break;
     52             }
     53         }
     54         for(int i=high+1;i>=high-1;i--){
     55             int nxx=mov(i,yy);
     56             if(nxx<=high&&nxx>=low){
     57                 hi=i;
     58                 break;
     59             }
     60         }
     61         if(lo>hi)return;
     62         low=lo,high=hi;
     63     }
     64     if(high-low+1>=n)
     65         for(int i=1;i<=n;i++)
     66             jump[i]=tx;
     67     else 
     68         for(int i=low;i<=high;++i)
     69             jump[fx(i)]=tx;
     70 }
     71 inline void move(R int &x,R int &y,R int k)
     72 {
     73     memset(v,0,sizeof v);
     74     memset(vk,0,sizeof vk);
     75     if(k>=(m-y+1)){// can arrive 1 column
     76         k-=(m-y+1);
     77         x=mof(x,y);
     78         y=1;
     79     }
     80     v[x]=1,vk[x]=k;
     81     while(k>=m){
     82         k-=m;
     83         x=jump[x];
     84         if(v[x])
     85         {
     86             int len=vk[x]-k;
     87             if(k>=len){
     88                 int nu=k/len;
     89                 k-=nu*len;
     90             }
     91         }
     92         v[x]=1,vk[x]=k;
     93     }
     94     while(k--)  x=fx(mov(x,y++));
     95 }
     96 int main()
     97 {
     98     n=read(),m=read();
     99     for(R int i=1;i<=n;++i)
    100         for(int j=1;j<=m;++j)
    101             a[i][j]=read();
    102     for(int i=1;i<=n;i++)
    103         jump[i]=mof(i,1);
    104     const int Q=read();
    105     R int x=1,y=1;
    106     for(R int q=1;q<=Q;++q)
    107     {    
    108         R char opt[16];
    109         scanf("%s",opt);
    110         if(opt[0]=='m')
    111         {
    112             int k=read();
    113             move(x,y,k);
    114             printf("%d %d
    ",x,y);
    115         }
    116         else 
    117         {
    118             R int xx=read(),yy=read(),w=read();
    119             a[xx][yy]=w;
    120             for(int i=xx-1;i<=xx+1;i++)
    121                 update(fx(i),fy(yy-1));
    122         }
    123     }
    124     return 0;
    125 }
    View Code

    T3[C. 优美序列]「ST表」「莫队」

    60%算法

    性质对于给定的区间[x,y],找出最大值和最小值,比较mx-mi是否等于y-x

    若不等则说明还有[mi,mx]内的点没有包含,那么再扩展x,y

    扩展方式是:记录每个值的所在位置pos[i],找到[mi,mx]内的极值对应y,x

    然后不断反复扩展,直到$mx-mi==y-x$

    80%算法

    用ST表维护两个数组的两个极值

    100%算法

    毒瘤卡常+莫队优化

    将询问按照尽量从里向外的方式排序,1.若上一个区间的ans范围大于该区间的原始长度,直接赋值,2.并且把该区间长度缩小至上一个,以供下一个区间使用

    3.若这个区间虽然不满足上一个要求,但它的最值和上一个相同,也直接赋值

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define R register
     7 using namespace std;
     8 inline int read()
     9 {
    10     R int x=0;char ch=getchar();
    11     while(ch>'9'||ch<'0')ch=getchar();
    12     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    13     return x;
    14 }
    15 const int maxn=100005;
    16 struct node{
    17     int l,r,id,mx,mi;
    18 }q[maxn];
    19 int n,a[maxn],pos[maxn],lg[maxn],al[maxn],ar[maxn];
    20 int ax[17][maxn],ai[17][maxn];
    21 int bx[17][maxn],bi[17][maxn];
    22 inline bool cmp(node a,node b){return (a.l==b.l)?a.r<b.r:a.l>b.l;}
    23 inline void ST_pre()
    24 {
    25     for(R int i=1;i<=n;++i){
    26         ax[0][i]=ai[0][i]=a[i],
    27         bx[0][i]=bi[0][i]=pos[i];
    28         if(i!=1)lg[i]=lg[i>>1]+1;
    29     }
    30     const int t=lg[n]+1;
    31     for(R int j=1;j<t;++j)
    32         for(R int i=1;i<=n-(1<<j)+1;++i){
    33              ax[j][i]=max(ax[j-1][i],ax[j-1][i+(1<<(j-1))]);
    34             ai[j][i]=min(ai[j-1][i],ai[j-1][i+(1<<(j-1))]);
    35             bx[j][i]=max(bx[j-1][i],bx[j-1][i+(1<<(j-1))]);
    36             bi[j][i]=min(bi[j-1][i],bi[j-1][i+(1<<(j-1))]);
    37         }
    38 }
    39 inline int ask(R int l,R int r,R int pd)
    40 {
    41     const int t=lg[r-l+1];
    42     if(pd==1)return max(ax[t][l],ax[t][r-(1<<t)+1]);
    43     if(pd==2)return min(ai[t][l],ai[t][r-(1<<t)+1]);
    44     if(pd==3)return max(bx[t][l],bx[t][r-(1<<t)+1]);
    45     if(pd==4)return min(bi[t][l],bi[t][r-(1<<t)+1]);
    46 }
    47 int main()
    48 {
    49     //freopen("sequence24.in","r",stdin);
    50     n=read();
    51     for(R int i=1;i<=n;++i){
    52         a[i]=read(),
    53         pos[a[i]]=i;
    54     }
    55     ST_pre();
    56     const int Q=read();
    57     for(R int i=1;i<=Q;++i){
    58         q[i].l=read(),
    59         q[i].r=read(),
    60         q[i].id=i;
    61     }
    62     sort(q+1,q+1+Q,cmp);
    63     for(R int i=1;i<=Q;++i)
    64     {
    65         if(q[i].l<=q[i-1].l&&q[i].r>=q[i-1].r&&al[q[i-1].id]<=q[i].l&&ar[q[i-1].id]>=q[i].r){
    66             al[q[i].id]=al[q[i-1].id],ar[q[i].id]=ar[q[i-1].id];
    67             q[i].l=q[i-1].l,q[i].r=q[i-1].r;
    68             continue;
    69         }
    70         R int x=q[i].l,y=q[i].r;
    71         R int mx=ask(x,y,1),mi=ask(x,y,2);
    72         q[i].mx=mx,q[i].mi=mi;
    73         if(q[i].mx==q[i-1].mx&&q[i].mx==q[i].mi){
    74             al[q[i].id]=al[q[i-1].id],ar[q[i].id]=ar[q[i-1].id];
    75             continue;
    76         }
    77         while(1)
    78         {
    79             y=ask(mi,mx,3),x=ask(mi,mx,4);
    80             if(y-x==mx-mi)break;
    81             mx=ask(x,y,1),mi=ask(x,y,2);
    82         }
    83         al[q[i].id]=x,ar[q[i].id]=y;
    84         
    85     }
    86     for(R int i=1;i<=Q;++i)
    87         printf("%d %d
    ",al[i],ar[i]);
    88 }
    View Code
    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    多态
    重载 特点
    java 测量运行时间 单位:毫秒
    java 源代码 二分查找 Arrays
    java 同步 synchronized
    云服务器,价格其实不便宜,但为什么还要用呢
    网站访问优化(二):开启apache服务器gzip压缩
    CXF整合Spring开发WebService
    网站访问优化,未完待续
    网站访问优化,未完待续
  • 原文地址:https://www.cnblogs.com/casun547/p/11312067.html
Copyright © 2011-2022 走看看