题意:

给你n 个数(1~n的排列), m 个操作, 

操作1: 将指定区间 升序排序

操作2: 将指定区间降序排列。

最后问你某一个的位置的数是多少?

思路:

神题~~~

没想到这能二分去做。。


直接二分那个数是啥。 然后模拟整个操作。

将比二分的值小的赋为0, 大的赋为1,  

然后就是模拟操作

对于升序排序, 直接看看这个区间有多少个0, 多少个1,(线段树维护0的个数即可。)

将前面赋值0 , 后面赋值1即可。

降序同理。

只要看最后那个位置是0 还是1 还是答案即可。

这样 这个问题转换成了  二分 + 线段树区间赋值。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 100000 + 10;
int n, m, K;
int a[maxn];
struct node{

    int op;
    int l,r;
    void read(){
        scanf("%d%d%d",&op ,&l, &r);
    }
}p[maxn];


int b[maxn];

struct neode{
    int l,r;
    int setv;
    int sum;
}nod[maxn<<2];

void pushup(int o){
    nod[o].sum = nod[o<<1].sum + nod[o<<1|1].sum;
}

void pushdown(int o){
    if (nod[o].setv != -1){
        int lson = o << 1;
        int rson = o << 1 | 1;
        nod[lson].setv = nod[rson].setv = nod[o].setv;
        if (nod[o].setv == 0){
            nod[lson].sum = nod[lson].r - nod[lson].l + 1;
            nod[rson].sum = nod[rson].r - nod[rson].l + 1;
        }
        else {
            nod[lson].sum = 0;
            nod[rson].sum = 0;
        }
        nod[o].setv = -1;
    }
}
void build(int l,int r,int o){
    nod[o].l = l;
    nod[o].r = r;
    nod[o].setv = -1;
    if (l == r){
        nod[o].sum = (b[l] == 0 ? 1 : 0);
        return ;
    }
    int m = l + r >> 1;
    build(l, m, o<<1);
    build(m+1, r, o<<1|1);
    pushup(o);
}


void update(int L,int R,int c, int l,int r,int o){
    if (L > R) return ;
    if (L <= l && r <= R){
        nod[o].setv = c;
        if (c == 0){
            nod[o].sum = r - l + 1;
        }
        else {
            nod[o].sum = 0;
        }
        return;
    }
    pushdown(o);
    int m = l + r >> 1;
    if (m >= L){
        update(L,R, c, l, m, o<<1);

    }
    if (m < R){
        update(L, R, c, m+1, r, o<<1|1);

    }
    pushup(o);
}
int query(int pos,int l,int r,int o){
    if (l == r){
        if (nod[o].setv != -1) return nod[o].setv;
        return nod[o].sum == 0;
    }

    pushdown(o);
    int m = l + r >> 1;

    if (m >= pos){
        return query(pos, l, m ,o<<1);
    }
    else {
        return query(pos, m+1, r, o<<1|1);
    }
}



int Query(int L,int R,int l,int r,int o){

    if (L <= l && r <= R){

        return nod[o].sum;
    }
    int m = l + r >> 1;
    int ans = 0;
    pushdown(o);
    if (m >= L){
        ans += Query(L,R,l, m, o<<1);
    }
    if (m < R){
        ans += Query(L, R, m+1, r, o<<1|1);
    }
    return ans;
}

int pos;
void deal(int mid){


    for (int i = 1; i <= n; ++i){
        if (a[i] == mid) pos = i;


        if (a[i] < mid) b[i] = 0;
        else if (a[i] > mid) b[i] = 1;
        else b[i] = mid;
    }

    build(1, n, 1);


    for (int i = 0; i < m; ++i){
        if (p[i].op == 0){
            int zero = Query(p[i].l, p[i].r, 1, n, 1);
            if (pos >= p[i].l && pos <= p[i].r){
                update(p[i].l, p[i].l + zero - 1, 0, 1, n, 1);
                update(p[i].l + zero, p[i].l + zero, mid, 1, n, 1);
                pos = p[i].l + zero;
                update(p[i].l + zero + 1, p[i].r, 1, 1, n, 1);
            }
            else {
                update(p[i].l, p[i].l + zero - 1, 0, 1, n, 1);
                update(p[i].l + zero, p[i].r, 1, 1, n, 1);
            }
        }
        else {
            int zero = Query(p[i].l, p[i].r, 1, n, 1);
            if (pos >= p[i].l && pos <= p[i].r){
                update(p[i].r - zero + 1, p[i].r, 0, 1, n, 1);
                update(p[i].r - zero , p[i].r - zero, mid, 1, n, 1);
                update(p[i].l, p[i].r - zero - 1, 1, 1, n, 1);
                pos = p[i].r - zero;
            }
            else {
                update(p[i].r - zero + 1, p[i].r, 0, 1, n, 1);
                update(p[i].l, p[i].r - zero, 1, 1, n, 1);
            }
        }
    }
}

void solve(){

    int l = 1, r = n;
    while(l <= r){
        int m = l + r >> 1;
        deal(m);
        if (pos == K) {
            printf("%d\n", m);
            return;
        }
        int val = query(K, 1, n, 1);

        if (val == 0){
            r = m -1;
        }
        else if (val == 1) l = m + 1;
    }


}

int main(){

    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n, &m);
        for (int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
        }
        for (int i = 0; i < m; ++i){

            p[i].read();
        }

        scanf("%d",&K);
        solve();
    }
    return 0;
}
/**
1
6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

ans = 5;

**/



DZY Loves Sorting


Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 547    Accepted Submission(s): 162



Problem Description


a[1..n]. It is a permutation of integers  1∼n.

Now he wants to perform two types of operations:

0lr: Sort  a[l..r] in increasing order.

1lr: Sort  a[l..r] in decreasing order.

After doing all the operations, he will tell you a position  k, and ask you the value of  a[k].


 



Input


t, denoting the number of testcases.

t testcases follow. For each testcase:

First line contains  n,m.  m is the number of operations.

Second line contains  n space-separated integers  a[1],a[2],⋯,a[n], the initial sequence. We ensure that it is a permutation of  1∼n.

Then  m lines follow. In each line there are three integers  opt,l,r to indicate an operation.

Last line contains  k.

( 1≤t≤50,1≤n,m≤100000,1≤k≤n,1≤l≤r≤n,opt∈{0,1}. Sum of  n in all testcases does not exceed  150000. Sum of  m in all testcases does not exceed  150000)


 



Output


a[k] after performing all  m operations.


 



Sample Input


1 6 3 1 6 2 5 3 4 0 1 4 1 3 6 0 2 4 3


 



Sample Output


Hint


 



Source


BestCoder Round #76 (div.1)


 



Recommend


wange2014   |   We have carefully selected several similar problems for you:   6107  6106  6105  6104  6103 


 




Statistic | 

Submit | 

Discuss | 

Note