Heteroaryl [Title] [CodeForces 1172F] Nauuo and Bug [Data] [segment tree structure]

Description

Given a sequence of a length n and p an integer
of m groups query, given a query each interval \ ([l, r] \
) You need to give the following results of this process

ans = 0 
for i from l to r
{
    ans = ans + a[i]
    if ans > p then ans = ans - p;
}
return ans 

\ (n \ leq 10 ^ 6 \)
\ (m <= 2 \ times10 ^ 5 \)
\ (p \ leq10 ^ 9 \)
\ (- 10 ^ 9 \ leq a_i \ leq10 ^ 9 \)

Solution

Obviously within a range of up to p times the interval length will Save
This means that if we set a function \ (f (x) \) initial is x, after the interval \ ([l, r] \ ) after answer, \ (f (x) \) apparently by a \ (r-l + 2 \ ) constituting the slope of a linear function period 1, and the intercept p is the difference between two adjacent

Still further, the length of each section can be found is \ (O (p) \) of

Then we can consider the maintenance function with the tree line, tree line for each section a note of each segment endpoint, the query is very simple, direct from zero plus the contribution of this paragraph and the next interval half belong to that period.

The key achievements are
considered sub-interval left and right sub-interval has been built, consider combining them, in fact, is a complex process functions.
In particular implementation, the enumeration of all segments of the left sub-intervals, calculate the corresponding range interval, then the right with a pointer to find the legitimate right segment.
Since the length of each segment are \ (O (P) \) , and therefore the position of each number is a constant pointer movable stage.

The total time complexity is \ (O (n \ log n
+ m \ log ^ 2 n) \) can refer to the program.

Code

//Copyright Reserved by BAJim_H
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
typedef long long LL;
const int N=2000005;
const LL INF=(LL)1e16;
using namespace std;
vector<LL> f[N];
int t[N][2],d[200],a[N],n,n1,mo,q;
LL sm[N];
template <class I>
void read(I &x)
{
    x=0;char ch=getchar();I v=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') v=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    x=x*v;
}
void build(int k,int l,int r)
{
    if(l==r) {f[k].push_back(-INF),f[k].push_back(mo-a[l]);sm[k]=a[l];return;}
    int mid=(l+r)>>1;
    t[k][0]=++n1,build(t[k][0],l,mid);
    t[k][1]=++n1,build(t[k][1],mid+1,r);
    int x=t[k][0],y=t[k][1],rx=f[x].size(),ry=f[y].size();
    f[k].resize(rx+ry-1,INF);       
    for(int i=0,j=0;i<rx;++i)
    {
        LL xl=f[x][i],xr=(i+1!=rx)?f[x][i+1]-1:INF,yl=xl+sm[x]-(LL)i*mo,yr=xr+sm[x]-(LL)i*mo;
        while(j>0&&f[y][j]>yl) j--;
        while(j<ry&&f[y][j]<=yl) j++;
        if(j) j--;
        while(j<ry&&f[y][j]<=yr) f[k][i+j]=min(f[k][i+j],max(xl,f[y][j]-sm[x]+(LL)i*mo)),j++;
    }
    f[k][0]=-INF;
    sm[k]=sm[t[k][0]]+sm[t[k][1]];
}
void find(int k,int l,int r,int x,int y)
{
    if(x<=l&&r<=y) {d[++d[0]]=k;return;}
    int mid=(l+r)>>1;
    if(x<=mid) find(t[k][0],l,mid,x,y);
    if(y>mid) find(t[k][1],mid+1,r,x,y);
}
LL query(int x,int y)
{
    d[0]=0;find(1,1,n,x,y);
    LL c=0;
    fo(i,1,d[0]) 
        c+=sm[d[i]]-(LL)mo*(upper_bound(f[d[i]].begin(),f[d[i]].end(),c)-f[d[i]].begin()-1);
    return c;
}
int main()
{
    cin>>n>>q>>mo;
    fo(i,1,n) read(a[i]);
    n1=1;
    build(1,1,n); 
    fo(i,1,q)
    {
        int x,y;
        read(x),read(y);
        printf("%lld\n",query(x,y));
    }
}

Reproduced in: https: //www.cnblogs.com/BAJimH/p/11054456.html

Guess you like

Origin blog.csdn.net/weixin_33910434/article/details/93245070