zoukankan      html  css  js  c++  java
  • Greedy Sequence(主席树-区间小于每个数的最大值)

    You're given a permutation aaa of length nnn (1≤n≤1051 le n le 10^51n105).

    For each i∈[1,n]i in [1,n]i[1,n], construct a sequence sis_isi by the following rules:

    1. si[1]=is_i[1]=isi[1]=i;
    2. The length of sis_isi is nnn, and for each j∈[2,n]j in [2, n]j[2,n], si[j]≤si[j−1]s_i[j] le s_i[j-1]si[j]si[j1];
    3. First, we must choose all the possible elements of sis_isi from permutation aaa. If the index of si[j]s_i[j]si[j] in permutation aaa is pos[j]pos[j]pos[j], for each j≥2j ge 2j2, ∣pos[j]−pos[j−1]∣≤k|pos[j]-pos[j-1]|le kpos[j]pos[j1]k (1≤k≤1051 le k le 10^51k105). And for each sis_isi, every element of sis_isi must occur in aaa at most once.
    4. After we choose all possible elements for sis_isi, if the length of sis_isi is smaller than nnn, the value of every undetermined element of sis_isi is 000;
    5. For each sis_isi, we must make its weight high enough.

    Consider two sequences C=[c1,c2,...cn]C = [c_1, c_2, ... c_n]C=[c1,c2,...cn] and D=[d1,d2,...,dn]D=[d_1, d_2, ..., d_n]D=[d1,d2,...,dn], we say the weight of CCC is higher than that of DDD if and only if there exists an integer kkk such that 1≤k≤n1 le k le n1kn, ci=dic_i=d_ici=di for all 1≤i<k1 le i < k1i<k, and ck>dkc_k > d_kck>dk.

    If for each i∈[1,n]i in [1,n]i[1,n], ci=dic_i=d_ici=di, the weight of CCC is equal to the weight of DDD.

    For each i∈[1,n]i in [1,n]i[1,n], print the number of non-zero elements of sis_isi separated by a space.

    It's guaranteed that there is only one possible answer.

    Input

    There are multiple test cases.

    The first line contains one integer T(1≤T≤20)T(1 le T le 20)T(1T20), denoting the number of test cases.

    Each test case contains two lines, the first line contains two integers nnn and kkk (1≤n,k≤1051 le n,k le 10^51n,k105), the second line contains nnn distinct integers a1,a2,...,ana_1, a_2, ..., a_na1,a2,...,an (1≤ai≤n1 le a_i le n1ain) separated by a space, which is the permutation aaa.

    Output

    For each test case, print one line consists of nnn integers ∣s1∣,∣s2∣,...,∣sn∣|s_1|, |s_2|, ..., |s_n|s1,s2,...,sn∣ separated by a space.

    ∣si∣|s_i|si∣ is the number of non-zero elements of sequence sis_isi.

    There is no space at the end of the line.

    样例输入

    2
    3 1
    3 2 1
    7 2
    3 1 4 6 2 5 7

    样例输出

    1 2 3
    1 1 2 3 2 3 3
    解题思路: 题目意思找[x-k,x+k]区间里小于其的最大值,然后在用那个数去更新 位置一个单调递减的数列!
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int tot=0,t,n,k;
     4 const int maxn=1e5+5;
     5 struct Node{
     6     int l,r,sum;
     7 }A[maxn*32];
     8 int arr[maxn],root[maxn];
     9 int ma[maxn],res[maxn];
    10 
    11 void updata(int left,int right,int &now,int pre,int value){
    12     A[++tot]=A[pre],now=tot,A[now].sum++;
    13     if(left==right) return;
    14     int mid=left+right>>1;
    15     if(mid>=value) updata(left,mid,A[now].l,A[pre].l,value);
    16     else updata(mid+1,right,A[now].r,A[pre].r,value);
    17 }
    18 
    19 int query(int left,int right,int x,int y,int value){   //返回的小于某个数的最大值
    20     if(A[y].sum-A[x].sum==0) return -1;   //当前区间的个数为0则减枝;
    21     if(left==right){      //递归到叶子节点
    22         return left<value?left:-1;
    23     }
    24     int mid=left+right>>1;
    25     if(value<=mid+1||A[A[y].r].sum-A[A[x].r].sum==0){  //查找的数在左边或者右边没有shu
    26         return query(left,mid,A[x].l,A[y].l,value);
    27     }
    28     int t=query(mid+1,right,A[x].r,A[y].r,value);  //先查找右边
    29     if(t==-1) query(left,mid,A[x].l,A[y].l,value);
    30     else return t;
    31 
    32 }
    33 
    34 int main(){
    35     ios::sync_with_stdio(false);
    36     cin>>t;
    37     while(t--){
    38         memset(root,0,sizeof(root)),tot=0,memset(A,0,sizeof(A));
    39         cin>>n>>k;
    40         for(int i=1;i<=n;i++) cin>>arr[i],ma[arr[i]]=i;
    41         for(int i=1;i<=n;i++) updata(1,n,root[i],root[i-1],arr[i]);
    42         res[1]=1;
    43         for(int i=2;i<=n;i++){
    44             int L=max(1,ma[i]-k);
    45             int R=min(n,ma[i]+k);
    46             int flag=query(1,n,root[L-1],root[R],i);
    47             if(flag==-1) res[i]=1;
    48             else res[i]=res[flag]+1;   //递推的公式
    49         }
    50         for(int i=1;i<=n;i++){
    51             printf("%d%c",res[i],i==n?'
    ':' ');
    52         }
    53     }
    54     return 0;
    55 }
    主席树
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int t,n,m;
     4 const int maxn=1e5+5;
     5 int sum[maxn<<2];
     6 int ma[maxn],res[maxn],arr[maxn];
     7 void updata(int rt) { sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); }  //区间存的是最大值
     8 void build(int l,int r,int rt){
     9     sum[rt]=0;
    10     if(l==r) {return;}
    11     int mid=l+r>>1;
    12     build(l,mid,rt<<1);
    13     build(mid+1,r,rt<<1|1);
    14     updata(rt);
    15 }
    16 void add(int l,int r,int rt,int pos,int value){
    17     if(l==r) {sum[rt]=value;return;}
    18     int mid=l+r>>1;
    19     if(mid>=pos) add(l,mid,rt<<1,pos,value);
    20     else add(mid+1,r,rt<<1|1,pos,value);
    21     updata(rt);
    22 }
    23 int query(int l,int r,int rt,int L,int R,int value){
    24     if(L<=l&&R>=r) return sum[rt];
    25     int mid=l+r>>1;
    26     int ans=0;
    27     if(mid>=L) ans=max(ans,query(l,mid,rt<<1,L,R,value));
    28     if(R>mid) ans=max(ans,query(mid+1,r,rt<<1|1,L,R,value));
    29     return ans;
    30 }
    31 
    32 int main(){
    33     ios::sync_with_stdio(false);
    34     cin>>t;
    35     while(t--){
    36         cin>>n>>m;
    37         for(int i=1;i<=n;i++){
    38             cin>>arr[i];
    39             ma[arr[i]]=i;
    40         }
    41         build(1,n,1);
    42         for(int i=1;i<=n;i++){
    43             int L=max(1,ma[i]-m);
    44             int R=min(n,ma[i]+m);
    45             int x=query(1,n,1,L,R,i);   //小于这个数的最大值
    46             add(1,n,1,ma[i],i);   //后添加必定保证是小于其的数
    47             res[i]=res[x]+1;
    48         }
    49         for(int i=1;i<=n;i++)
    50             printf("%d%c",res[i],i==n?'
    ':' ');
    51     }
    52     return 0;
    53 }
    线段树
  • 相关阅读:
    设计模式:备忘录模式??
    jQuery总结
    MYSQL(三)
    MYSQL(二)
    MYSQL(一)
    Web.xml配置详解
    Spring-JDBC通用Dao
    网络七层协议的形象说明
    网络编程概念
    JSP 9 大内置对象详解
  • 原文地址:https://www.cnblogs.com/qq-1585047819/p/11517017.html
Copyright © 2011-2022 走看看