「模拟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\n");
22        else printf("%lld\n",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\n",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\n",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\n",sum_maxn[b[i]-1]);
79         }
80         else if(orz[i]=='>')
81         {
82             printf("%lld\n",sum_maxn[kx]-sum_maxn[b[i]]);
83         }
84         else printf("%lld\n",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\n",c);
16             return 0;
17          }   
18          printf("%lld AC\n",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",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\n",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\n",f[n]%mod);
28 }
View Code

 

posted @ 2019-08-22 16:10  Wwb_star  阅读(146)  评论(1编辑  收藏  举报