【ZOJ-4028】 LIS(2018浙江省赛-E题)

Input

There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains an integer n (1<=n<=10^5), indicating the length of the original sequence.

The second line contains n integers f1,f2.....fn (1<=fi<=n) seperated by a space, indicating the helper sequence.

For the following n lines, the i-th line contains two integers li and ri(0<=li<=ri<=2*10^9), indicating the range sequences.

It's guaranteed that the original sequence exists, and the sum of n of all test cases will not exceed .

Output

For each test case output one line containing n integers separated by a space, indicating the original sequence. If there are multiple valid answers, print any of them.

Please, DO NOT print extra spaces at the end of each line, or your solution may be considered incorrect!

Sample Input
4
6
1 2 3 2 4 3
0 5
2 4
3 3
1 2
3 5
1 5
5
1 2 1 3 1
100 200
200 300
200 400
400 500
100 500
7
1 2 3 1 1 4 2
0 3
0 3
0 3
0 3
0 3
0 3
0 3
2
1 1
1 2
2 3
Sample Output
1 2 3 2 5 3
200 300 200 500 200
0 1 2 0 0 3 1
2 2

题意:

第一个数代表输入的组数,每组第一个数表示一个序列的数字个数,下面是序列中,以第ai个数结尾所能构成的最长上升子序列,其后的数字是每个数的上限以及下限

思路:

1,每个相同长度结尾的数字单独提出来构成的数组一定是递减的,比如3 3中,如果后面的比前面的大,那后面的3就会变成4。

2,每个相差1的相邻两个数,前面的一定可以和后面这个构成上升序列,比如3 3 4,如果第二个3不能和4构成上升序列,那他前面一定有个3可以和他构成上升序列,就说明前面的那个3一定比这个3的数要小,这个3就会变成4,不成立。

3,当后面的数连起来,比如3 4 4 4的时候,这个3一定可以满足所有的4,原理同2,另外,因为4都是递减的,所以满足了最后一个4就可以了。

代码:

#include<bits/stdc++.h>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
vector<int>di[100005];
vector<int>ma[100005];
int qian[100005];int hou[100005];
int you[100005];int chu[100005];
int main()
{
    int zu,shu;int jin;
    while(~scanf("%d",&zu)){
    while(zu--){
        scanf("%d",&shu);
        int da=0;
        for(int i=0;i<=shu;i++){di[i].clear();ma[i].clear();}
        for(int i=0;i<shu;i++){
            scanf("%d",&jin);
            di[jin].push_back(i);
            if(jin>da)da=jin;
            you[i]=di[jin+1].size();
        }
        for(int i=0;i<shu;i++){scanf("%d%d",&qian[i],&hou[i]);}
        for(int i=0;i<di[da].size();i++){
            int wei=di[da][i];
            if(i==0){chu[wei]=hou[wei];ma[da].push_back(chu[wei]);continue;}
            int zhi=chu[di[da][i-1]];if(zhi>hou[wei])zhi=hou[wei];
            chu[wei]=zhi;ma[da].push_back(zhi);
        }
        for(int i=da-1;i>=1;i--){
            for(int j=0;j<di[i].size();j++){
                int wei=di[i][j];int zhi;
                if(ma[i+1].size()>=you[wei]+1&&(j==di[i].size()-1||you[wei]!=you[di[i][j+1]])){
                   if(j==di[i].size()-1)zhi=ma[i+1][ma[i+1].size()-1]-1;
                   else{
                       int jian;
                       //if(i==3)printf("%d %d\n",you[di[i][j+1]],you[wei]);
                       jian=you[di[i][j+1]]-you[wei];
                       zhi=ma[i+1][you[wei]+jian-1]-1;
                   }
                }
                else zhi=hou[wei];
                if(zhi>hou[wei])zhi=hou[wei];
                if(j==0){chu[wei]=zhi;ma[i].push_back(zhi);continue;}
                if(zhi>chu[di[i][j-1]])zhi=chu[di[i][j-1]];
                chu[wei]=zhi;ma[i].push_back(zhi);
            }
        }
        for(int i=0;i<shu;i++){
            if(i==0)printf("%d",chu[i]);
            else printf(" %d",chu[i]);
        }
        puts("");
    }
    }
    return 0;
}
/*
5
5
1 2 3 3 4
0 5
0 5
0 5
0 40
0 4
6
1 2 3 2 4 3
0 5
2 4
3 3
1 2
3 5
1 5
5
1 2 1 3 1
100 200
200 300
200 400
400 500
100 500
7
1 2 3 1 1 4 2
0 3
0 3
0 3
0 3
0 3
0 3
0 3
2
1 1
1 2
2 3
*/

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值