• 「模拟8.22」爬山(二分)·学数数(单调队列)·七十和十七(数学)


    开学了,状态很差,没有考好。

    T1是水题,话说我还非得打个对拍真是.......

    直接二分就好了

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 int n,d,a,b;
     5 int work(int x)
     6 {
     7     if(a+(x*d)<=b+((n-1)-x)*d)return 1;
     8     return 0;
     9 }
    10 int work2(int x)
    11 {
    12     if(a+((n-1-x)*d)<=b+x*d)return 1;
    13 }
    14 signed main()
    15 {
    16     //freopen("text.in","r",stdin);
    17     //freopen("a.out","w",stdout);
    18     scanf("%lld%lld%lld%lld",&n,&d,&a,&b);
    19     if(n==1)
    20     {
    21        if(a!=b)printf("0
    ");
    22        else printf("%lld
    ",a);
    23        return 0;
    24     }
    25     int maxn=0;
    26     int l=0;int r=n-1;
    27     while(l+1<r)
    28     {
    29           int mid=(l+r)>>1;
    30           if(work(mid))l=mid;
    31           else r=mid;
    32     }
    33     if(work(r))
    34     {
    35        maxn=a+(r*d);
    36     }
    37     else if(work(l))maxn=a+(l*d);
    38     swap(a,b);
    39     l=0;r=n-1;
    40     while(l+1<r)
    41     {
    42           int mid=(l+r)>>1;
    43           if(work(mid))l=mid;
    44           else r=mid;
    45     }
    46     if(work(r))
    47     {
    48        maxn=max(a+(r*d),maxn);
    49     }
    50     else if(work(l))maxn=max(a+(l*d),maxn);   
    51     printf("%lld
    ",maxn);
    52 }
    53 /*
    54 1 3 1 2
    55 */
    View Code

     

    T2

    以后绝对不用线段树查前趋

    然后我们考虑用单调队列查前趋最大

    正着扫一边,做单调下降序列

    倒着扫一边,做单调不上升序列

    这是因为会出现重复的情况,

    例如a[1]=4,a[2]=2,a[3]=1,a[4]=2,a[5]=4;

    当我们算位置2和4时肯定会把1-5算两次,

    既然这样我们不妨把一个区间弄成左开右闭

    这样我们相当于以2为中点,1和4为两侧的答案+以4为中点,1-5为两侧的答案,这样保证在算2时不会出现跨过4的区间所以正确

    然后就没了,记得离散化

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define MAXN 210000
     4 #define inf 0x7fffffff
     5 using namespace std;
     6 int yuan[MAXN],b[MAXN];
     7 int tot,n,m,kx;
     8 int dp[MAXN];int end;
     9 struct node{int id,a;}e[MAXN];
    10 int l[MAXN],r[MAXN];char orz[MAXN];
    11 int get_sum(int l,int head,int last,int r)
    12 {
    13     int anss=0;
    14     int l_len=head-l;int r_len=r-last;
    15     //printf("l_len=%lld r_len=%lld
    ",l_len,r_len);
    16     anss+=l_len*r_len;
    17     anss+=(last-head+1)*r_len;
    18     anss+=(last-head+1)*l_len;
    19     int len=last-head+1;
    20     anss+=(len*(len+1))/2;    
    21     return anss;
    22 }int sum_maxn[MAXN];
    23 signed main()
    24 {
    25     //freopen("text.in","r",stdin);
    26     //freopen("kkk.out","w",stdout);
    27     scanf("%lld%lld",&n,&m);    
    28     for(int i=1;i<=n;++i)
    29     {
    30         scanf("%lld",&yuan[i]);e[i].a=yuan[i],e[i].id=i;
    31     }    
    32     tot=n;
    33     for(int i=1;i<=m;++i)
    34     {
    35         cin>>orz[i];
    36         scanf("%lld",&b[i]);
    37         yuan[++tot]=b[i];
    38     }
    39     sort(yuan+1,yuan+tot+1);
    40     kx=unique(yuan+1,yuan+tot+1)-yuan-1;
    41     for(int i=1;i<=n;++i)
    42     {
    43         e[i].a=lower_bound(yuan+1,yuan+kx+1,e[i].a)-yuan;
    44     }
    45     for(int i=1;i<=m;++i)
    46     {
    47         b[i]=lower_bound(yuan+1,yuan+kx+1,b[i])-yuan;
    48     }
    49     dp[0]=0;e[0].a=inf;end=0;
    50     for(int i=1;i<=n;++i)
    51     {
    52        while(e[i].a>=e[dp[end]].a)
    53        {
    54             end--;
    55        }
    56        l[i]=dp[end]+1;
    57        dp[++end]=e[i].id;
    58     }
    59     dp[0]=n+1;e[n+1].a=inf;end=0;
    60     for(int i=n;i>=1;--i)
    61     {
    62        while(e[i].a>e[dp[end]].a)
    63        {
    64             end--;
    65        }
    66        r[i]=dp[end]-1;
    67        dp[++end]=e[i].id;
    68     }
    69     for(int i=1;i<=n;++i)
    70     {
    71        sum_maxn[e[i].a]+=get_sum(l[i],i,i,r[i]);
    72     }
    73     for(int i=2;i<=kx;++i)sum_maxn[i]+=sum_maxn[i-1];
    74     for(int i=1;i<=m;++i)
    75     {
    76         if(orz[i]=='<')
    77         {
    78             printf("%lld
    ",sum_maxn[b[i]-1]);
    79         }
    80         else if(orz[i]=='>')
    81         {
    82             printf("%lld
    ",sum_maxn[kx]-sum_maxn[b[i]]);
    83         }
    84         else printf("%lld
    ",sum_maxn[b[i]]-sum_maxn[b[i]-1]);
    85     }
    86 }
    View Code

     弱弱的附上对拍

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 signed main()
     5 {
     6     int c=0;
     7     while(true)
     8     {
     9          c++;
    10          system("./pai");
    11          system("./ac");
    12          system("./kkk");    
    13          if(system("diff -b -B ac.out kkk.out"))
    14          {
    15             printf("%lld WA
    ",c);
    16             return 0;
    17          }   
    18          printf("%lld AC
    ",c);           
    19     }
    20 }
    21 /*
    22 g++ pai.cpp -o pai
    23 ./pai
    24 g++ ac.cpp -o ac
    25 ./ac
    26 g++ kkk.cpp -o kkk
    27 ./kkk
    28 g++ ran.cpp -o ran
    29 ./ran
    30 */
    View Code

    随机数据生成

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 using namespace std;
     4 int random(int x)
     5 {
     6      return (long long)rand()*rand()%x;
     7 }
     8 void work()
     9 {
    10      int x=random(10)+1;
    11      if(x%3==0)cout<<"> ";
    12      else if(x%4==0)cout<<"< ";
    13      else cout<<"= ";
    14 }
    15 signed main()
    16 {
    17     freopen("text.in","w",stdout);
    18     srand((unsigned)time(0));
    19     int n=random(10)+1;int m=10;
    20     printf("%lld %lld
    ",n,m);
    21     for(int i=1;i<=n;++i)printf("%lld ",random(10)+1);
    22     cout<<endl;
    23     for(int i=1;i<=m;++i)
    24     {
    25         work();
    26         printf("%lld
    ",random(10)+1);
    27     }
    28 }
    View Code

    T3

    这是个打表题

    于是我们设g[i]表示已经排好i-1个数,现在插入i时的方案

    插入1,只需1步

    插入2,需要1步将2提前,加上1的步数

    插入3,需要将3提前,加上将1,2提前的步数

    ......

    插入i需0步

    这样g[i]=g[1-(i-1)]+1,然后我们可以看出这就是2^(i-1)

    然后我们就可以把列出

    ans=sigema(sigema(2^(j-1)))(1<=j<=i-1)(1<=i<=n)

    然后根据数学知识就可以变成ans=ans+(2^(i-1))-1(1<=i<=n)

    除以!i的逆元即可

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define MAXN 210000
     4 using namespace std;
     5 int f[MAXN],ni[MAXN];
     6 const int mod=1e9+7;int n;
     7 int poww(int x,int y)
     8 {
     9     int ans=1;
    10     while(y)
    11     {
    12         if(y&1)ans=ans*x%mod;
    13         x=x*x%mod;
    14         y>>=1;
    15     }
    16     return ans%mod;
    17 }
    18 signed main()
    19 {
    20    scanf("%lld",&n);
    21    ni[0]=1;ni[1]=1;
    22    for(int i=2;i<=n;++i)ni[i]=(mod-mod/i)*ni[mod%i]%mod;
    23    for(int i=1;i<=n;++i)
    24    {
    25        f[i]=f[i-1]+(poww(2,i-1)-1+mod)%mod*ni[i]%mod;
    26    }
    27    printf("%lld
    ",f[n]%mod);
    28 }
    View Code
  • 相关阅读:
    1016: 写出来吧
    从硬件工程师转到纯软件开发,回顾那些岁月
    用大白话聊聊JavaSE -- 自定义注解入门
    数组中的一些常用方法总结
    js中的隐式转换
    开源OSS.Social微信项目进阶介绍
    .Net开源oss项目进度更新(含小程序接口)
    windows下部署免费ssl证书(letsencrypt)
    完成OSS.Http底层HttpClient重构封装 支持标准库
    谈javascript变量声明
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11394953.html
Copyright © 2020-2023  润新知