CodeForces 193D. Two Segments [tree line]

Portal
make this question is because of the opportunity for the last question rotten Bridge Cup 2013, although that question of violence could go, but seeing the tree line approach Gangster introduction, I feel refreshed and I know for a line of trees,Sure enough, the tree line is omnipotent

The meaning of problems

You give a \ (n-\) of the full array \ (A \) , you can select from two sections do not overlap, if all of the two sections are arranged in ascending order is a tolerance \ (1 \) of arithmetic sequence, it is a legitimate program, if the same number interval contains two different sets, then as a program. I asked a total of how many legitimate programs.

answer

Consider a positive integer in the range if it is known \ ([l, r] \ ) in the original full array \ (A \) is divided into the \ (K \) period, at which time \ (R & lt. 1 + \) , in the following case:

  • If \ (r + 1 \) and \ ([l, r] \ ) to any of a number not adjacent, then \ ([l, r + 1 ] \) is divided into \ (k + 1 \) section .
  • If \ (r + 1 \) and \ ([l, r] \ ) in a number of adjacent, then \ ([l, r + 1 ] \) is still divided into \ (K \) segments.
  • If \ (r + 1 \) and \ ([l, r] \ ) of two adjacent numbers, then \ ([l, r + 1 ] \) is divided into (k-1 \) \ segment.

In this case can be a \ (O (n ^ 2) \) algorithm not go into here. This question is because the data range \ (n-\ Le 300 \, 000 \) , \ (O (^ n-2) \) algorithm is not acceptable.
However, according to the above-described changes of the segment, we have found that the interval can be changed, i.e., to \ (f [l, r] \) represents \ ([l, r] \ ) number of segments to be split, if known \ (F [. 1, R & lt], F [2, R & lt], ..., F [R & lt, R & lt] \) , these time intervals are added \ (R & lt. 1 + \) , the following circumstances:

  • If \ ([1, r] \ ) is not the number of those in \ (r + 1 \) in \ (A \) adjacent, then:
    \ [F [I, R & lt +. 1] = F [I, R & lt ] +1 \]

  • If \ ([1, r] \ ) there is only one number \ (X \) and \ (r + 1 \) in \ (A \) adjacent, \ ([I, R & lt +. 1] (. 1 \ le i \ le x) \) is divided and the number of segments will \ ([i, r] \ ) same as \ (r + 1 \) is and \ (X \) firmly affixed together ♂ thing; and \ ([i, r + 1 ] (x + 1 \ le i \ le r + 1) \) than \ ([i, r] \ ) number of segments divided by the \ (1 \) , the reason is \ ([ i, r] \) are not counted and \ (r + 1 \) adjacent, then \ (r + 1 \) may constitute a separate section. Therefore, this case can be expressed as:
    \ [\ the begin {the aligned} F [I, R & lt +. 1] & = F [I, R & lt] &, &&. 1 \ Le & I \ Le X \\ F [I, R & lt +. 1] & = f [i, r] +1 &, && x + 1 \ le & i \ le r + 1 \ end {aligned} \]

  • If \ ([l, r] \ ) there are two numbers \ (x, y (x < y) \) and \ (r + 1 \) in \ (A \) adjacent, then \ ([ i, r + 1] (1 \ le i \ le x) \) the number of stages is divided ratio \ ([i, r] \ ) less \ (1 \) , because originally \ (x, y \) is split , adding \ (r + 1 \) after the two sections together; and \ ([i, r + 1 ] (x + 1 \ le i \ le y) \) and \ ([i, r] \ ) are equal, since only \ (Y \) a number and \ (r + 1 \) paste; and \ ([i, r + 1 ] (y + 1 \ le i \ le r + 1) \) ratio \ ( [i, r] \) multi \ (1 \) . It can be expressed as:
    \[ \begin{aligned} f[i,r+1] &= f[i,r]-1 &, &&1\le &i\le x\\ f[i,r+1] &= f[i,r] &, &&x+1\le &i\le y\\ f[i,r+1] &= f[i,r]+1 &, &&y+1\le &i\le r+1 \end{aligned} \]

So we can use the tree line to maintain decide \ (r \) when (f [i, r] \ ) \ value, according to the meaning of the questions, each addition \ (r + 1 \) after only need to query the tree line the value \ (1 \) or \ (2 \) number of leaf nodes on the list.

Briefly about the wording of the tree line

Because under \ (f [l, r] \) properties can know that the minimum line segment of leaf nodes \ (1 \) , then to check \ (1 \) and \ (2 \) number, only minimum maintenance interval and the minimum value and the minimum value of the number \ (1 + \) number on the list.
Note pushup operation wording, the statistical range minimum, then the query about the minimum subtree minimum number, in particular, do not forget to count the full minimum \ (+ 1 \) number.

Code

#include <iostream>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N=3e5+10;
int n,a[N],p[N];

struct SegTree{
    #define mid (l+r>>1)
    int num1[N*4],num2[N*4],minv[N*4],tag[N*4];
    void pushdown(int id){
        minv[id<<1]+=tag[id];tag[id<<1]+=tag[id];
        minv[id<<1|1]+=tag[id];tag[id<<1|1]+=tag[id];
        tag[id]=0;
    }
    void pushup(int id){
        minv[id]=min(minv[id<<1],minv[id<<1|1]);
        num1[id]=num2[id]=0;
        if(minv[id<<1]==minv[id]) num1[id]+=num1[id<<1],num2[id]+=num2[id<<1];
        else if(minv[id<<1]==minv[id]+1) num2[id]+=num1[id<<1];
        if(minv[id<<1|1]==minv[id]) num1[id]+=num1[id<<1|1],num2[id]+=num2[id<<1|1];
        else if(minv[id<<1|1]==minv[id]+1) num2[id]+=num1[id<<1|1];
    }
    void build(int id,int l,int r){
        num1[id]=r-l+1;
        if(l==r) return;
        build(id<<1,l,mid);
        build(id<<1|1,mid+1,r);
    }
    void upd(int id,int l,int r,int L,int R,int x){
        if(L<=l&&r<=R) {minv[id]+=x;tag[id]+=x;return;}
        if(tag[id]) pushdown(id);
        if(L<=mid) upd(id<<1,l,mid,L,R,x);
        if(R>mid) upd(id<<1|1,mid+1,r,L,R,x);
        pushup(id);
    }
    int ask(int id,int l,int r,int L,int R){
        if(L<=l&&r<=R) {
            if(minv[id]==1) return num1[id]+num2[id];
            if(minv[id]==2) return num1[id];
            return 0;
        }
        if(tag[id]) pushdown(id);
        int res=0;
        if(L<=mid) res+=ask(id<<1,l,mid,L,R);
        if(R>mid) res+=ask(id<<1|1,mid+1,r,L,R);
        return res;
    }
    #undef mid
}tr;

int main(){
    scanf("%d",&n);
    for(int i=1,x;i<=n;i++) scanf("%d",&x),p[x]=i;
    LL ans=0;
    tr.build(1,1,n);
    for(int i=1;i<=n;i++){
        a[p[i]]=i;
        int x=a[p[i]-1],y=a[p[i]+1];
        if(x>y) swap(x,y);
        if(x) tr.upd(1,1,n,1,x,-1),tr.upd(1,1,n,y+1,i,1);
        else if(y) tr.upd(1,1,n,y+1,i,1);
        else tr.upd(1,1,n,1,i,1);
        ans+=tr.ask(1,1,n,1,i);
        //cout<<"->"<<ans<<endl;
    }
    ans-=n;
    cout<<ans<<endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/BakaCirno/p/12466819.html