6374. [2019.10.04] Ward NOIP2019 analog [realm of life and death]

topic

Subject to the effect

To give you a number of columns, each can choose any two adjacent numbers \ (X \) and \ (Y \) , its deletion and insertion in the original position \ (X + 2Y \) .
Each time a query interval, the interval of the above operation. Find the last remaining number is the largest number.
The answer needs modulo.


Reflections on History

See this problem, the first thought is: this question it is necessary to put forward a maximum, but also modulo, so it must be greedy.
However, not ......
\ (O (the n-^ 3) \) violence can be fought directly to the interval \ (DP \) . But I did not play.
In fact, the biggest bottleneck is that I need more than size, however the number is too large, it will blow up ......
this problem itself faces problems of violence unfriendly ......


Correct

In fact, when I discovered the game on an interesting property:
We operate as the entire range is divided into two sections, the section behind coefficient multiplied by two, then both sides continue recursion process.
Easy to find, assuming \ (2 ...... {k_i} \ ) for the first \ (I \) coefficients of terms, the \ (. 1 \ Leq K_i \ Leq K_ {I}. 1-+ 1'd \) , \ (= 0 k_1 \)
may be the answer sequence as several \ (k_i \) of the arithmetic sequence at the beginning of each series of arithmetic is \ (1 \) at the end of the previous (first arithmetic sequence except).

However, there is a more magical conclusion: \ (K_i \) either \ (1 \) , or is \ (k_ {i-1}
+1 \) simply prove it:
For an arithmetic sequence, remember what it is with. If greater than and equal to \ (0 \) , then it is connected to one of the preceding arithmetic sequence will be better later; is less than \ (0 \) , then the beginning of the \ (K \) is set to \ (1 \) most excellent.

Do not consider all inquiries. Suppose the query \ (1 \) starts, the incremental method is configured such arithmetic sequence.
First, add a node, \ (K_i \) to \ (1 \) , and then try to merge with the front.
If greater than or equal \ (0 \) , to go to the front. Try to continue with the merger front after pick up.
Or do not go to the front.
Obviously this is not a problem.

Next consider how to deal with inquiries section. First off it, according to the right point range ordering, ask hang on the right spot.
In the statistical answer when left to find the point where the arithmetic sequence. When you can find a half or disjoint-set.
Left behind series points where the arithmetic of those arithmetic sequence of number and directly add up. Prefix and implementation can be used.
Left point arithmetic sequence might split into two portions, a direct calculation like that behind. Calculation of the time can be pre-start \ (sum_i = \ sum_. 1 {J} = {I} ^ 2 ^ ja_j \) , behind \ (SUM \) subtracting \ (L-sum_. 1} {\) , divided by the \ (2 ^ L \) .

Why after the division arithmetic sequence will not change it?
In fact, only need to prove that the merger will not back up, and this will not continue to divide on the line.
Back and certainly negative, so the front has changed and they do not merge up.
If the split (assuming split into \ (B \) and \ (C \) , divided at the left of \ (A \) ), the original and for the \ (A + 2 ^ xB + 2 ^ {x + y C} \) , and after the split becomes \ (2 ^ B + yC \) . If it is split, it becomes \ (B + C \) ..
Each multiplied by \ (X ^ 2 \) , plus \ (A \) , respectively, it becomes \ (A + 2 ^ xB + 2 ^ {x + y} C \) and \ (A + 2 ^ xB + 2 ^ xC \)
since the former must be optimized, so that \ (2 ^ yC \ GEQ C \) , so \ (C> 0 \) .
So it will not split the better.

When implemented, it is easy to explode long long. Indeed, while a positive number is large, but it is the smallest negative number is not too small. Because a minimum, it must be an arithmetic sequence is only one negative (if there are several numbers merger came up behind the back of those few numbers and some non-negative, then, and not much smaller). So the minimum is \ (- 2E9 \) .
If the number is greater than \ (2E9 \) , after that it will never become negative. Denoted \ (2e9 + 1 \) on the line.
Time to achieve a true record and used to calculate the answer to (a norm); a false record and used to size ratio.


Code

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
#define ll long long
#define INF 2000000000
#define mo 1000000007
inline ll my_pow(ll x,int y){
    ll res=1;
    for (;y;x=x*x%mo,y>>=1)
        if (y&1)
            res=res*x%mo;
    return res;
}
int n,m;
int a[N];
struct Query{
    int l,r,num;
} q[N];
inline bool cmpq(Query a,Query b){return a.r<b.r;}
ll ans[N];
ll _2,pow2[N],ipow2[N],bpow2[N],g[N];
int st[N],top;
ll sum[N],rs[N],pre[N];
int main(){
    freopen("border.in","r",stdin);
    freopen("border.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    _2=my_pow(2,mo-2);
    pow2[0]=bpow2[0]=ipow2[0]=1;
    for (int i=1;i<=n;++i){
        pow2[i]=pow2[i-1]*2%mo;
        bpow2[i]=bpow2[i-1]*2;
        bpow2[i]=(bpow2[i]>INF?INF+1:bpow2[i]);
        ipow2[i]=ipow2[i-1]*_2%mo;
        g[i]=(g[i-1]+pow2[i]*a[i])%mo;
    }
    for (int i=1;i<=m;++i)
        scanf("%d%d",&q[i].l,&q[i].r),q[i].num=i;
    sort(q+1,q+m+1,cmpq);
    st[top=1]=1,pre[1]=sum[1]=rs[1]=a[1];
    int j=1;
    for (;q[j].r<=1;++j)
        ans[q[j].num]=(a[1]+mo)%mo;
    for (int i=2;i<=n;++i){
        st[++top]=i;
        sum[top]=2*a[i];
        rs[top]=2ll*(a[i]+mo)%mo;
        while (top>1 && sum[top]>=0){
            rs[top-1]=(rs[top-1]+rs[top]*pow2[st[top]-st[top-1]-(top==2)])%mo;
            sum[top-1]=sum[top-1]+sum[top]*bpow2[st[top]-st[top-1]-(top==2)];
            sum[top-1]=(sum[top-1]>INF?INF+1:sum[top-1]);
            top--;
        }
        pre[top]=(pre[top-1]+rs[top])%mo;
        st[top+1]=i+1;
        for (;j<=m && q[j].r<=i;++j){
            int l=2,r=top,x=1;
            while (l<=r){
                int mid=l+r>>1;
                if (st[mid]<=q[j].l)
                    l=(x=mid)+1;
                else
                    r=mid-1;
            }
            ans[q[j].num]=((pre[top]-pre[x]+mo)+(g[st[x+1]-1]-g[q[j].l-1])*ipow2[q[j].l]%mo+mo)%mo;
        }
    }
    for (int i=1;i<=m;++i)
        printf("%lld\n",ans[i]);
    return 0;
}

to sum up

Feel too dishes ......
the face of greedy questions, we must dare to conclusions ......

Guess you like

Origin www.cnblogs.com/jz-597/p/11628758.html