Greedy Sequence(线段树动态维护区间最大值)

You're given a permutation aa of length nn (1 \le n \le 10^51≤n≤105).

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

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

Consider two sequences C = [c_1, c_2, ... c_n]C=[c1​,c2​,...cn​] and D=[d_1, d_2, ..., d_n]D=[d1​,d2​,...,dn​], we say the weight of CC is higher than that of DD if and only if there exists an integer kk such that 1 \le k \le n1≤k≤n, c_i=d_ici​=di​ for all 1 \le i < k1≤i d_kck​>dk​.

If for each i \in [1,n]i∈[1,n], c_i=d_ici​=di​, the weight of CC is equal to the weight of DD.

For each i \in [1,n]i∈[1,n], print the number of non-zero elements of s_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 \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 nn and kk (1 \le n,k \le 10^51≤n,k≤105), the second line contains nn distinct integers a_1, a_2, ..., a_na1​,a2​,...,an​ (1 \le a_i \le n1≤ai​≤n) separated by a space, which is the permutation aa.

Output

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

|s_i|∣si​∣ is the number of non-zero elements of sequence s_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

题意:第一行给出t(测试组数),接下来每组数据,第一行给出n(下一行数列的长度:数的个数),k(每次要查询的区间半径) ,第二行给出n个数,即数列a[],然后每次对于长度等同于n的每个数都是1的数列b[],数据给出的数列中每个数的数值(即a[i].val)为每次要修改的在b[]中的位置,该位置的数要加上以a[]中这个数为中心,半径k的区间内比中心的这个数小的最大的数的数值(设为ans)所表示的位置处的b[]的数值(即:b[a[i].val]+=b[ans]),这样从a[]中的数值(即在b[]中的位置)从小到大开始依次修改b[],最终将b[]顺序输出即可。

思路:根据a[]初始的数列建立线段树并维护区间最大值,按a[]中数值从大到小的顺序依次修改当前数a[i].val对应的在线段树中对应的位置的值为0并用map记录其对应的ans(将中心的这个数记为0后,用线段树查询区间最大值即为半径k的区间内比中心的这个数小的最大的数的数值ans),最后按b[]中位置(即a[]的数值)从小到大依次对b[]进行操作(因为每次要修改的在b[]中某位置i的数要加上以a[]中这个数为中心,半径k的区间内中心的这个i小的最大的数的数值(设为ans)所表示的位置处的b[]的数值,所以每次i位置要加的数的位置一定在i位置之前,因此按b[]中位置(即a[]的数值)从小到大依次对b[]进行操作就保证了每次加的数一定为那个位置改完后最终确定的数),最后将b[]顺序输出即可。

完整代码:

#include 
#define int long long
using namespace std;
const int mxn=1e5+5;
int t,n,k,b[mxn],tree[mxn<<2];
typedef struct point
{
    int id,val;
}pi;
pi a[mxn];
mapmp;

int cmp(pi a,pi b)
{
    return a.val>b.val;
}

int cmp2(pi a,pi b)
{
    return a.val>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    pushup(p);
}

void modify(int p,int l,int r,int pos)
{
    if(l==r)
    {
        tree[p]=0;
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
    {
        modify(p<<1,l,mid,pos);
    }
    else{
        modify(p<<1|1,mid+1,r,pos);
    }
    pushup(p);
}

int query(int p,int l,int r,int a,int b)
{
    if(l>=a&&r<=b)
    {
        return tree[p];
    }
    int mid=(l+r)>>1;
    if(b<=mid)
    {
        return query(p<<1,l,mid,a,b);
    }
    if(a>mid)
    {
        return query(p<<1|1,mid+1,r,a,b);
    }
    return max(query(p<<1,l,mid,a,mid),query(p<<1|1,mid+1,r,mid+1,b));
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        mp.clear();
        for(int i=1;i<=n;i++)
            b[i]=1;
        for(int i=1;i<=n;i++)
            a[i].id=a[i].val=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i].val;
            a[i].id=i;
        }
        build(1,1,n);
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            modify(1,1,n,a[i].id);
            int l=a[i].id-k,r=a[i].id+k;
            if(l<1)
                l=1;
            if(r>n)
                r=n;
            int ans=query(1,1,n,l,r);
            mp[a[i].val]=ans;
        }
        sort(a+1,a+n+1,cmp2);
        for(int i=1;i<=n;i++)
            b[a[i].val]+=b[mp[a[i].val]];
        for(int i=1;i<=n-1;i++)
            cout<

 

你可能感兴趣的:(树)