码迷,mamicode.com
首页 > 其他好文 > 详细

Greedy Sequence(主席树-区间小于每个数的最大值)

时间:2019-09-13 18:04:26      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:board   main   ase   rate   nod   namespace   open   最大值   print   

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 n1ai?n) 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?\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?\n: );
51     }
52     return 0;
53 }
线段树

 

Greedy Sequence(主席树-区间小于每个数的最大值)

标签:board   main   ase   rate   nod   namespace   open   最大值   print   

原文地址:https://www.cnblogs.com/qq-1585047819/p/11517017.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!