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

    T1[A. Blue]

    贪心,对于每只青蛙,跳的时候尽量远,越远选择越多

    注意若用set实现,要先insert(0)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<set>
     7 #define R register
     8 using namespace std;
     9 inline int read()
    10 {
    11     int x=0;char ch=getchar();
    12     while(ch>'9'||ch<'0')ch=getchar();
    13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    14     return x;
    15 }
    16 const int maxn=1000005;
    17 int n,m,d,l;
    18 set<int>s;
    19 int main()
    20 {
    21     //freopen("blue4.in","r",stdin);
    22     int T=read();
    23     while(T--)
    24     {
    25         s.clear();s.insert(0);//it: set:3 4 5  ,upper_bound(6)->s.end();->cout<<*it的结果是s.size()
    26                     // it: set:5 upper_bound(4)->s.begin(),,若--it还会是begin(),而此时pos==0,x>=pos+d,却会跳过去
    27                     //总之set最好先insert(0);
    28         n=read(),m=read(),d=read(),l=read();
    29         for(R int i=1;i<=n;++i)
    30         {
    31             int x=read();
    32             s.insert(x);
    33         }
    34         if(d==l){puts("Excited");continue;}
    35         int pos=0,ans=0;
    36         while(s.size())
    37         {
    38             if(ans>=m)break;
    39             if(pos+d>=l)
    40             {
    41                 pos=0;ans++;
    42                 continue;
    43             }
    44             set<int>::iterator it=s.upper_bound(pos+d);
    45             int x=*--it;
    46             if(x<=pos)break;
    47             s.erase(x);
    48             pos=x;
    49         }
    50         if(pos+d>=l)ans++;
    51         if(ans>=m)puts("Excited");
    52         else printf("%d
    ",ans);
    53     }
    54 }
    View Code

     

     T2[B. Weed]

    线段树:以时间为下标,建一颗线段树,维护以下信息:

    1.s,这个区间的ans值,就是量2.na,这个区间的当前层数,3.nd这个区间还没有删完的层数

    那某个区间怎么会na与nd同时存在?  是因为这个区间中,删除操作在左面,而增加在右面,删除操作无法影响后面的,

    怎么维护:读入初始数据,建树和修改时,将子节点信息update到父节点是关键,

    分三种情况讨论,见代码注释

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define R register
     5 #define lc (k<<1)
     6 #define rc (k<<1|1)
     7 #define mid ((t[k].l+t[k].r)>>1)
     8 using namespace std;
     9 
    10 inline int read()
    11 {
    12     int x=0;char ch=getchar();
    13     while(ch>'9'||ch<'0')ch=getchar();
    14     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    15     return x;
    16 }
    17 const int maxn=2e5+5;
    18 int m,q;
    19 int b[maxn],v[maxn];
    20 struct node{
    21     int k,l,r,s,na,nd;
    22 }t[4*maxn];
    23 int cal(int k,int res)//k子树减去res后的s值
    24 {
    25     if(t[rc].na==res)return t[k].s-t[rc].s;//右儿子正好被减完,不能写成t[lc].s,这代表只考虑左儿子自己的s值,左右合并后就变了,
    26     if(t[rc].na>res)return t[k].s-t[rc].s+cal(rc,res);//右儿子比较多,还要加上cal
    27     if(t[rc].na<res)return cal(lc,res-t[rc].na+t[rc].nd);//右儿子太少了,减没了,所以不用加右儿子的s,但是t[rc].nd还要给前面减掉
    28 }
    29 void update(int k)
    30 {
    31     if(t[lc].na<=t[rc].nd)//左儿子不够减
    32     {
    33         t[k].nd=t[rc].nd+t[lc].nd-t[lc].na;//总的nd还要加上左儿子剩的
    34         t[k].s=t[rc].s;t[k].na=t[rc].na;//左儿子减没了
    35     }
    36     else if(t[rc].nd==0)//rc没减的
    37     {
    38         t[k].s=t[lc].s+t[rc].s;
    39         t[k].na=t[lc].na+t[rc].na;
    40         t[k].nd=t[lc].nd;
    41     }
    42     else//左儿子没被减完
    43     {
    44         t[k].nd=t[lc].nd;
    45         t[k].na=t[lc].na+t[rc].na-t[rc].nd;
    46         t[k].s=t[rc].s+cal(lc,t[rc].nd);//cal来计算左儿子被减之后的s
    47     }
    48 }
    49 void build(int k,int l,int r)
    50 {
    51     t[k].l=l,t[k].r=r;
    52     if(l==r)
    53     {
    54         int kk=t[k].l;
    55         if(b[kk]) t[k].nd=v[kk];
    56         else t[k].na=1,t[k].s=v[kk];
    57         return;
    58     }
    59     build(lc,l,mid);
    60     build(rc,mid+1,r);
    61     update(k);
    62 }
    63 void change(int k,int l,int r,int pos,int bl,int vl)
    64 {
    65     if(t[k].l==t[k].r)
    66     {
    67         if(bl) t[k].nd=vl,t[k].na=t[k].s=0;
    68         else t[k].na=1,t[k].s=vl,t[k].nd=0;
    69         return;
    70     }
    71     if(pos<=mid)change(lc,l,mid,pos,bl,vl);
    72     else change(rc,mid+1,rc,pos,bl,vl);
    73     update(k);
    74 }
    75 int main()
    76 {
    77 //    freopen("weed.in","r",stdin);
    78     m=read(),q=read();
    79     for(int i=1;i<=m;i++)
    80         b[i]=read(),v[i]=read();
    81     build(1,1,m);
    82     for(int i=1;i<=q;i++)
    83     {
    84         int k=read(),bl=read(),vl=read();
    85         change(1,1,m,k,bl,vl);
    86         printf("%d
    ",t[1].s);
    87     }
    88 }
    View Code

     

    T3[C. Drink]

    暴力可以水过,本渣渣就不写正解了,这个坑以后再填

    比较好打的暴力:从左上角开始向右枚举每个点放入队列中,然后从右上角开始,向下然后向左枚举,依次从队列中填入,$O(q*2*nm)$

    优化常数2:对于每一次翻转,四个点同时转,这样常数变为$1/4$

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #define R register
     5 using namespace std;
     6 char a[2005][2005],q[4000001];
     7 inline int read()
     8 {
     9     int x=0;char ch=getchar();
    10     while(ch>'9'||ch<'0')ch=getchar();
    11     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    12     return x;
    13 }
    14 int main()
    15 {
    16     //freopen("data","r",stdin);
    17     const int n=read(),m=read(),Q=read();
    18     for(R int i=1;i<=n;++i)
    19         for(R int j=1;j<=m;++j)
    20         {
    21             R char ch=getchar();
    22             while(ch<'0'||ch>'9')ch=getchar();
    23             a[i][j]=ch;
    24         }
    25     for(R int i=1;i<=Q;++i)
    26     {
    27         const int x=read(),y=read(),len=read();
    28         for(R int i=0;i<len/2;++i)
    29         {
    30             R int x1=x+i,x2=x+i,x3=x+len-1-i,x4=x+len-1-i,y1=y+i,y2=y+len-1-i,y3=y+len-1-i,y4=y+i;
    31             while(y1!=y+len-1-i)
    32             {
    33                 R int tt=a[x1][y1];
    34                 a[x1][y1]=a[x4][y4],a[x4][y4]=a[x3][y3],a[x3][y3]=a[x2][y2],a[x2][y2]=tt;
    35                 y1++,x2++,y3--,x4--;
    36             }
    37         }
    38     }
    39     for(R int i=1;i<=n;++i){
    40         for(R int j=1;j<=m;++j)
    41             printf("%c ",a[i][j]);
    42         puts("");
    43     }
    44 }
    View Code

     

    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    C#编写功能让你的系统导入注册表文件时不提示
    登陆框提示历史记录
    C# 操作系统防火墙
    C# 制作Java +Mysql+Tomcat 环境安装程序,一键式安装 (续集Tomcat 配置)
    C# 修饰符你记住了吗?
    C# 实现设置系统环境变量设置
    showModalDialog使用例子,父窗口向子窗口传递值
    C#后台无刷新页面弹出alert方法
    VS2008 无法启动调试.未安装Silverlight托管调试包 .
    在GridView中使用FindControl .
  • 原文地址:https://www.cnblogs.com/casun547/p/11331831.html
Copyright © 2011-2022 走看看