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

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

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?[j−1];
  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 2j≥2, ∣pos[j]−pos[j−1]∣≤k|pos[j]-pos[j-1]|\le k∣pos[j]−pos[j−1]∣≤k (1≤k≤1051 \le k \le 10^51≤k≤105). 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 n1≤k≤n, ci=dic_i=d_ici?=di? for all 1≤i<k1 \le i < k1≤i<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(1≤T≤20), 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^51≤n,k≤105), the second line contains nnn distinct integers a1,a2,...,ana_1, a_2, ..., a_na1?,a2?,...,an? (1≤ai≤n1 \le a_i \le n1≤ai?≤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 }

线段树

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

时间: 2024-10-07 23:52:51

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

hdu 5919 主席树(区间不同数的个数 + 区间第k大)

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 849    Accepted Submission(s): 204 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?

poj2104 主席树 区间K大 在线 无修改

关于主席树: 主席树(Chairman Tree)是一种离线数据结构,使用函数式线段树维护每一时刻离散之后的数字出现的次数,由于各历史版本的线段树结构一致,可以相减得出区间信息,即该区间内出现的数字和对应的数量,由于在线段树内,左子树代表的数字都小与右子树,便可像平衡树一样进行K大询问.新建一颗树是\(O(logn)\),查询一次也为\(O(logn)\). 比划分树好想&写多了,但是在POJ上比划分树慢一些. CODE: 1 #include <cstdio> 2 #include

hdu 4348 To the moon(主席树区间操作)

题目链接:hdu 4348 To the moon 题意: 给你n个数,有m个操作. 1.给区间[l,r]的所有数+d,并且时间戳+1 2.询问当前时间戳的区间和. 3.询问过去时间戳t的区间和. 4.退回到时间戳t. 题解: 直接上主席树. 不过区间操作的时候push_down空间似乎不是那么够用. 所有把push_down这个操作去掉. 用一个标记记录当前这个区间的累加. 询问的时候就将这个累加传下去.(具体看代码) 最后还有退回状态t的时候可以把cnt=root[t+1], 因为后面的内存

HDU - 4348 To the moon(主席树区间更新)

题目链接:To the moon 题意:给个数组,三种操作,第一种询问当前区间[l,r]的和,第二种给区间[l,r]的每一个数加上d,第三种询问在第几次修改后[l,r]的权值 题解:如果这题只询问区间和更新,简单建棵线段树维护区间和用延时标记就可以了,但是它询问第几次修改之后一段区间的值,这样的话刚才的方法就不好用,那我们可不可以,在每次修改之后的重新建一棵线段树呢?直接重新建的话空间会爆,这个时候就可以用??币的主席树(没学过主席树可以先做一下这个),每次的修改只会再新增logN个节点,先把给

HDU 4348 To the moon(主席树 区间更新)题解

题意: 给一个数组A[1] ~ A[n],有4种操作: Q l r询问l r区间和 C l r v给l r区间每个数加v H l r t询问第t步操作的时候l r区间和 B t返回到第t步操作 思路: 用主席树维护常规的线段树.我们之前已经知道了主席树单点更新,只要新增一条链就ok了,区间更新也有点差不多.我们每次要更新都用一个lazy标记,但是显然我们不能去更新那些已经存在的区间,那么我们就新建出所有要更新的区间.因为可持久化线段树有些结点不是自己的,所以我们不能直接简单的push up和pu

【hdu5306】Gorgeous Sequence 线段树区间最值操作

题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y$ :求 $[x,y]$ 内所有数的和. 多组测试数据,$\sum n,\sum m\le 10^6$ 题解 线段树区间最值操作 对于线段树上的一个节点,维护对应区间的:最大值 $mx$ .最大值个数 $c$ 及严格次大值 $se$ .那么对于一次区间最小值操作: 如果 $t\ge mx$ ,则这个

主席树区间第K大

主席树的实质其实还是一颗线段树, 然后每一次修改都通过上一次的线段树,来添加新边,使得每次改变就改变logn个节点,很多节点重复利用,达到节省空间的目的. 1.不带修改的区间第K大. HDU-2665 模板题 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt&qu

HDU 6278 主席树(区间第k大)+二分

Just h-index Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 438    Accepted Submission(s): 203 Problem Description The h-index of an author is the largest h where he has at least h papers wit

Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模

D. The Child and Sequence At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at him. A lot of important things were lost, in particular the favorite sequence of Picks. Fortunately, Picks remembers how to