[BZOJ4444] [Luogu 4155] [LOJ 2007] [SCOI2015] Flag Program (multiplication)

[BZOJ4444] [Luogu 4155] [LOJ 2007] [SCOI2015] Flag Program (multiplication)

Face questions

Problems face a long, slightly

analysis

Routine first ring is broken chain. For the range from l to r ring, when l <= r, we break it into two sections \ ([l, r], [M + l, M r +] \) , or broken into \ ([ L, R & lt + M], [M + L, R & lt + M + M] \) (broken into \ ([l + M, 2M ] \) may be)

Then define the interval [l, r] go to the other and it intersects the interval 1 "step." Then we can pretreatment interval i go out the right end of the maximum interval j step can be reached. Noting interval mutually exclusive, the left end of the first section first key, the second key point of the right sort. For the interval i, we find satisfying \ (l_i <l_j \ leq r_i \) maximum \ (l_j \) , so \ (r_j \) is to take one step maximum range can reach the right point. Since \ (l_j> L_i \) , so \ (r_j> r_i \) , otherwise the interval j i will be included. Since sorted, j clearly monotonic, two-hand sweep over it.

    sort(a+1,a+1+sz);
    int ptr=1;
    for(int i=1;i<=sz;i++){
        while(ptr<sz&&a[ptr+1].l<=a[i].r) ptr++;
        if(ptr!=i) anc[i][0]=ptr;
    }

But the enumeration is still walking step j \ (O (n ^ 2) \) can be optimized with a double. \ (ANC [i] [j] \) representing the interval point j i go right steps to reach the maximum number of intervals. This can be \ (O (n \ log n ) \) pretreatment.

When jumping from the beginning of query i, has jump \ (r_ {anc [i] [j]} \ geq l_i + M \) so far, the boundary condition should be noted

int query(int x){
    int ans=1;
    int r=a[x].l+len; //注意边界,比如3->5,5->1,1->3.必须要跳回原点3,所以是+len而不是+len-1 
    for(int i=log2n;i>=0;i--){
        if(anc[x][i]!=0&&a[anc[x][i]].r<=r){//如果右端点<=i+M,就继续跳
            ans+=(1<<i); 
            x=anc[x][i];
        }
    }
    if(anc[x][0]&&a[x].r<r){//上面求的是右端点<=i+M,可能跳到了<i+M的某一个位置,再跳一步就超过i+M,这种情况也是合法的。特判一下。
        ans++;
        x=anc[x][0];
    }
    return ans; //保证一定有解,所以不用判断a[x].r是否>=r
}

Code

#include<iostream>
#include<cstdio>
#include<cstring> 
#include<cmath>
#include<algorithm> 
#define INF 0x3f3f3f3f
#define maxn 2000000
#define maxlogn 25
using namespace std;
int n,len;
struct seg{
    int l;
    int r;
    int id;
    seg(){
        
    }
    seg(int _l,int _r,int _id){
        l=_l;
        r=_r;
        id=_id;
    }
    friend bool operator  < (seg p,seg q){
        if(p.l==q.l) return p.r<q.r;
        else return p.l<q.l;
    }
}a[maxn+5]; 
int sz;
int log2n; 
int ans[maxn+5];
int anc[maxn+5][maxlogn+5];

int query(int x){
    int ans=1;
    int r=a[x].l+len; //注意边界,比如3->5,5->1,1->3.必须要跳回原点3,所以是+len而不是+len-1 
    for(int i=log2n;i>=0;i--){
        if(anc[x][i]!=0&&a[anc[x][i]].r<=r){
            ans+=(1<<i); 
            x=anc[x][i];
        }
    }
    if(anc[x][0]&&a[x].r<r){
        ans++;
        x=anc[x][0];
    }
    return ans; 
}
int main(){
    int l,r;
    scanf("%d %d",&n,&len);
    log2n=log2(n*2);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&l,&r);
        if(l<=r){
            a[++sz]=seg(l,r,i);
            a[++sz]=seg(l+len,r+len,i+n);
        }else{
            a[++sz]=seg(l,r+len,i);
            a[++sz]=seg(l+len,r+len+len,i+n);
        }
    }
    sort(a+1,a+1+sz);
    int ptr=1;
    for(int i=1;i<=sz;i++){
        while(ptr<sz&&a[ptr+1].l<=a[i].r) ptr++;
        if(ptr!=i) anc[i][0]=ptr;
    }
    for(int j=1;j<=log2n;j++){
        for(int i=1;i<=sz;i++){
            anc[i][j]=anc[anc[i][j-1]][j-1];
        }
    }
    for(int i=1;i<=sz;i++){
        if(a[i].id<=n) ans[a[i].id]=query(i);//注意要跳过(l+n,r+n),否则l+len会超过2*len导致答案错误 
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
}

Guess you like

Origin www.cnblogs.com/birchtree/p/11518927.html