您的位置:首页 > 其它

HDU 5649 DZY Loves Sorting (二分 + 线段树)

2017-08-11 19:08 260 查看
题意:

给你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

DZY has a sequence 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

First line contains 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

For each testcase, output one line - the value of 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

5

Hint
1 6 2 5 3 4 -> [1 2 5 6] 3 4 -> 1 2 [6 5 4 3] -> 1 [2 5 6] 4 3. At last $a[3]=5$.

 

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: