FZU2018 level algorithm 2.10 second job number (weights tree line) in reverse order

topic:

  Nk like several recent studies reverse, a given number of columns a1 consisting of 1 ... n, a2, a3 ... an,

  Number in reverse order a1 a2 ... an is, the number is smaller than the number of a1, a2 and the number of reverse number is a3 ... .an than a2 small numbers, and so on.

  For example, the number of columns is the inverse number sequence 5,3,4,2,1 4,2,2,1,0.

  So, if a given number sequence in reverse order of the number of columns, you can not get him to restore the original series?

  ★ data input

  Each test data is a positive integer n. Column length represents the number (1 <= n <= 500), and the number of columns in the original range of values ​​is [1, n].

  Then enter n positive integers ai (0 <= ai <n)

  ★ data output

  Original series output, intermediate between the two numbers separated by a space.

Input Example Output Example
5
4 2 2 1 0
5 3 4 2 1

 

  Analysis of the problem, not difficult to find, when the first number filled in, all numbers except their own are behind it, so the first digit is 4. We can be 1-n as a set of all numbers, when the i-th ai has a smaller number than his, ai + 1 in the first set is a large number of i-th digit, then this number from the set delete. Since the value of n is too small (though not cross segment tree but not as small as for 500), may be used to complete the list, can be used for set maintenance complexity are $ O (n ^ {2}) $, of course, , set up and maintain written more convenient, it is recommended to maintain a set. Here to share $ O (nlogn) $ approach, using weights tree line.

First paste the code set

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=x;i>=y;i--)
#define pb push_back
#define fi first
#define se second
#define mes(a,b) memset(a,b,sizeof a)
const int inf=0x3f3f3f3f;

set<int> s;
set<int> ::iterator pos;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    rept(i,1,n)
        s.insert(i);
    rept(i,1,n)
    {
        if(i-1) cout<<" ";
        int x;
        cin>>x;
        pos=s.begin(); 
        for(int i=0;i<x;i++,pos++);
        cout<<*pos;
        s.erase(pos);
    }
    cout<<"\n";
    return 0;
}

 

  For the number of all 1-n, the completion segment tree, each of the i-th marked point to several of the array, maintenance interval maximum value for the segment tree, each input ai, to find the first segment is greater than the number of ai point, that has left the interval left to find the range of greater than ai, left and right query interval no interval. Suppose i-th array of bi, bi the segment tree is assigned a value 0, then the $ [bi + 1, n] $ interval of each element 1 can be reduced.

 

AC paste the code segment tree

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define pb push_back
#define fi first
#define se second
#define mes(a,b) memset(a,b,sizeof a)

const int maxn=505;
ll arrcy[100005];
class Tree//线段树 
{
    public:
        int l,r;
        ll plus,val;
        Tree()
        {
            l=r=val=plus=0;
        }
}tree[maxn<<2];

void build(int id,int l,int r);
void add(int id,int l,int r,ll num);
void push_down(int id);
int find(int id,int num);
int main()
{
    int n,x,ans;
    cin>>n;
    build(1,1,n);
    rep(i,0,n)
    {
        cin>>x;
        ans=find(1,x);
        add(1,ans+1,n,-1);
        add(1,ans,ans,-n);
        cout<<ans<<" ";
    }
    return 0;
}

void build(int id,int l,int r)
{
    tree[id].l=l;
    tree[id].r=r;
    if(l==r)
    {
        tree[id].val=l;
        return ;
    }
    int mid=(l+r)/2;
    build(id*2,l,mid);
    build(id*2+1,mid+1,r);
    tree[id].val=max(tree[id*2].val,tree[id*2+1].val);
}
void add(int id,int l,int r,ll num)
{
    if(tree[id].l>=l&&tree[id].r<=r)
    {
        tree[id].plus+=num;
        tree[id].val+=num;
        return ;
    }
    if(tree[id].l>r||tree[id].r<l) return ;
    push_down(id);
    if(tree[id*2].r>=l) add(id*2,l,r,num);
    if(tree[id*2+1].l<=r) add(id*2+1,l,r,num);
    tree[id].val=max(tree[id*2].val,tree[id*2+1].val);    
}
void push_down(int id)
{
    rept(j,id*2,id*2+1)
    {
        tree[j].val+=tree[id].plus;
        tree[j].plus+=tree[id].plus; 
    }
    tree[id].plus=0;
}
int find(int id,int num)
{
    if(tree[id].l==tree[id].r) return tree[id].l;
    push_down(id);
    if(tree[id*2].val>num) return find(id*2,num);
    else return find(id*2+1,num);
}

 

Guess you like

Origin www.cnblogs.com/FZUzyz/p/11516357.html