zoukankan      html  css  js  c++  java
  • Codeforces878E. Numbers on the blackboard

    $n leq 100000$的数列,数字范围$-1e9,1e9$,现$q leq 1e5$个每次问在一个区间玩游戏,能得到的最大的数。“游戏”:选相邻两个数$a_x,a_y$,然后把他们删掉,变成$a_x+2a_y$,直到序列中只剩一个数。答案$mod 1e9+7$。

    单次询问可用贪心解决:首先第一个数系数一定是1,后面的数的系数是$2^k,kgeq 1$且$k$不会比上一个数的$k$多2以上。用一块表示给某个区间分配了系数2,4,8,16,。。。,也就是这个区间从左到右一个个合并,那么在数列右边加入一个新的数时,如果这个数是负数,那给他新开一块,否则合并到上一块中,若上一块的答案因此变成了正的,那就继续往前合并。

    多次询问只需离线一下,记一下每个块的位置,然后按上面的方法模拟,询问时二分一下就好了。不过要注意,询问时可能左端点处不是一个完整块,这时需要把那个块的后缀单独拿出来算答案。

    有个大问题:数字很大,如何判断大小以决定某个块是否要往前并?可以发现负权值最小只到2e9,因此超过2e9的正权值记成2e9+1就行了。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 //#include<math.h>
     5 //#include<set>
     6 //#include<queue>
     7 //#include<vector>
     8 #include<algorithm>
     9 #include<stdlib.h>
    10 using namespace std;
    11 
    12 #define LL long long
    13 int qread()
    14 {
    15     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
    16     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
    17 }
    18 
    19 //Pay attention to '-' , LL and double of qread!!!!
    20 
    21 int n,m;
    22 #define maxn 100011
    23 const int mod=1e9+7;
    24 
    25 int a[maxn],pos[maxn],bin[maxn],inv[maxn],sum[maxn],lp=0,val[maxn],vv[maxn],svv[maxn];
    26 struct Ques{int l,r,id; bool operator < (const Ques &b) const {return r<b.r;} }q[maxn];
    27 int ans[maxn];
    28 
    29 int WWW(LL v) {return v>2000000001?2000000001:v;}
    30 
    31 int main()
    32 {
    33     n=qread(); m=qread();
    34     bin[0]=inv[0]=1; for (int i=1;i<=n;i++)
    35         a[i]=qread(),bin[i]=(bin[i-1]<<1)%mod,inv[i]=1ll*inv[i-1]*((mod+1)>>1)%mod,
    36         sum[i]=((sum[i-1]+1ll*a[i]*bin[i])%mod+mod)%mod;
    37     for (int i=1;i<=m;i++) {q[i].l=qread(); q[q[i].id=i].r=qread();}
    38     sort(q+1,q+1+m);
    39     
    40     pos[lp=1]=1; int j=1; val[1]=a[1]*2; vv[1]=svv[1]=((a[1]*2)%mod+mod)%mod;
    41     while (j<=m && q[j].r==1) ans[q[j].id]=(a[1]+mod)%mod,j++;
    42     for (int i=2;i<=n;i++)
    43     {
    44         if (a[i]<=0) pos[++lp]=i,val[lp]=2*a[i],vv[lp]=(a[i]*2ll%mod+mod)%mod,svv[lp]=(svv[lp-1]+vv[lp])%mod;
    45         else
    46         {
    47             int cur=WWW(0ll+val[lp]+bin[pos[lp]-pos[lp-1]+1]*1ll*a[i]);
    48             int cvv=(vv[lp]+bin[pos[lp]-pos[lp-1]+1]*1ll*a[i])%mod; lp--;
    49             while (lp && cur>0)
    50             {
    51                 cur=WWW(0ll+val[lp]+(pos[lp]-pos[lp-1]>31?2000000001:bin[pos[lp]-pos[lp-1]])*1ll*cur);
    52                 cvv=(vv[lp]+bin[pos[lp]-pos[lp-1]]*1ll*cvv)%mod; lp--;
    53             }
    54             val[++lp]=cur; pos[lp]=i; vv[lp]=cvv; svv[lp]=(svv[lp-1]+vv[lp])%mod;
    55         }
    56         while (j<=m && q[j].r==i)
    57         {
    58             if (q[j].l==q[j].r) {ans[q[j].id]=(a[i]+mod)%mod; j++; continue;}
    59             int l=q[j].l+1,Ans=(a[q[j].l]+mod)%mod;
    60             int L=1,R=lp;
    61             while (L<R)
    62             {
    63                 int mid=(L+R)>>1;
    64                 if (pos[mid]>=l) R=mid; else L=mid+1;
    65             }
    66             Ans=(Ans+svv[lp]-svv[L])%mod; Ans=(Ans+mod)%mod;
    67             Ans=(Ans+(sum[pos[L]]-sum[l-1]+mod)*1ll*inv[l-1])%mod;
    68             ans[q[j].id]=Ans;
    69             j++;
    70         }
    71     }
    72     
    73     for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    java接口变量问题
    FileInputStream与BufferedInputStream的对比
    eclipse使用javaFX写一个HelloWorkld
    Windows 安装Java与配置环境变量
    asp.net core处理中文的指南
    修改release management client对应的服务器的地址
    在server2012安装tfs遇到的问题:KB2919355
    release management客户端无法连接到release management server的问题解决
    如何升级PowerShell
    VS2010下调试.NET源码
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9190467.html
Copyright © 2011-2022 走看看