spoj Permutacja 4310(线段树)

http://www.spoj.pl/problems/AE5B2/

SPOJ Problem Set (classical)

4310. Permutacja

Problem code: AE5B2

 

You are given a sequence of positive integers a1, a2, . . . , an. We would like to order the numbers from 1 to n in such a way, that the i-th number is not greater than ai (for each i). In other words, we are looking for a permutation p of numbers from 1 to n, which satisfies: pi ≤ ai for each 1 ≤ i ≤ n. There is one more problem, the sequence ai may change over time. . .

Input

The first line of standard input contains one integer n (1 ≤ n ≤ 200 000), the number of elements of the ai sequence. In the second line, there is a sequence of n positive integers ai (1 ≤ ai ≤ n), separated by single spaces. The third line contains one integer m (0 ≤ m ≤ 500 000), representing the number of modifications made to the ai sequence. The following m lines describe these modifications. Each description consists of two integers ji and wi (1 ≤ ji, wi ≤ n for 1 ≤ i ≤ m), separated by single spaces and meaning that ji-th element of the sequence becomes wi. The operations take place in turns, so the i-th modification is applied to the sequence altered by (i − 1) previous modifications.

Output

Your program should output exactly m + 1 lines to the standard output. Each of those lines should contain one word TAK (meaning YES) or NIE (meaning NO). The word in the first line should tell if there exists a permutation p, which satisfies pi ≤ ai for each i (for the original ai sequence), whereas the words from following lines answer the question whether there exist any (potentially different) permutations that satisfy the given conditions for the ai sequence after each modification.

Example

For the input data:

5
3 4 3 2 5
2
5 4
1 5

the correct result is:

TAK
NIE
TAK

Explanation of the example. For the original ai sequence, the condition is satisfied by permutation 2, 4, 3, 1, 5. After the first modification, the sequence becomes 3, 4, 3, 2, 4 and for this sequence no valid permutation exists. After the second modification, the sequence is 5, 4, 3, 2, 4. An example of a permutation p satisfying all constraints for this sequence is 5, 1, 3, 2, 4.


Added by:Race with time
Date:2009-05-03
Time limit:5s
Source limit:50000B
Languages:All except: ERL JS PERL 6
Resource:Algorithmic Engagements 2009

hide comments
2012-05-30 08:55:28 Adrian Jaskółka
Time limit is too strict. At Algorithmic Engagements I had AC, but here TL. Only fast I/O helped me to get AC.

参考资料:http://blog.sina.com.cn/s/blog_64018c250101296y.html

表示完全不会啊、。。

给一个A[1..n],问是否存在1~n的一个排列,满足所有p[i]<=A[i]。然后后面还有m次修改,每次修改某个位置的A[i]的值。

n,m<=200000 1<=A[i]<=n

Solution:

Sum[k]表示数组A[i]里包含多少个<=k的数字。然后这个判定性问题转化为是否所有Sum[k]<=k

然后就用线段树维护所有Sum[k]里,Max(Sum[k]-k)是不是小于等于0,如果是就满足,否则不满足。


//记录s[k]表示《=k的a[i]的个数
//只有当所有的s[k]-k<=0时才可行.
//用线段树维护区间的最大值


#include
#include
#include
using namespace std;
#define CY 200005
#define NODE 4*CY
int L[NODE];//保存左子树结点
int R[NODE];//保存右子树结点
int c[NODE];//保存线段树区间的最大值
int add[NODE];
int ar[CY];//保存输入的数据
int tb[CY];//保存输入的每个数的个数
int N;//多少个数
int M;//多少个询问
void build(int i,int lt,int rt)//建树
{
    L[i]=lt;
    R[i]=rt;
    if(lt==rt)
    {
        c[i]=tb[lt]-lt;保存线段树区间的最大值
        printf("c[i]=%d\n",c[i]);
        return;

    }
    int mid=(lt+rt)>>1;
    int lc=i<<1,rc=lc+1;
    build(lc,lt,mid);
    build(rc,mid+1,rt);
    c[i]=max(c[lc],c[rc]);//保存线段树区间的最大值
}
void init()//初始化
{
    memset(add,0,sizeof(add));
    memset(tb,0,sizeof(tb));
}
void input(int n)
{
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&ar[i]);
        tb[ar[i]]++;//表示at[i]的个数
        //printf("%d\n",tb[ar[i]]);
    }
    for(int i=1;i<=n;i++)//**********
    {
        tb[i]+=tb[i-1];
        //printf("tb[i-1]=%d     tb[i]=%d\n",tb[i-1],tb[i]);
    }
    scanf("%d",&M);
}
void update(int i,int p,int val)
{
    if(L[i]>=p)
    {
        add[i]+=val;
        return ;
    }
    if(p>R[i])
    {
        return;
    }
    int lc=i<<1,rc=lc+1;
    update(lc,p,val);
    update(rc,p,val);
    c[i]=max(c[lc]+add[lc],c[rc]+add[rc]);//保存线段树区间的最大值
}
void solve(int n)
{
    build(1,1,n);
    if(c[1]+add[1]<=0)
    {
        printf("TAK\n");
    }
    else
    {
        printf("NIE\n");
    }
    int j,w;
    for(int i=0;i
    {
        scanf("%d%d",&j,&w);//用w替代第J个数
        update(1,ar[j],-1);//*************
        update(1,ar[j]=w,1);
        if(c[1]+add[1]<=0)
        {
            printf("TAK\n");
        }
        else
        {
            printf("NIE\n");
        }
    }
}
int main()
{
    while(scanf("%d",&N)!=EOF)
    {
        init();//初始化
        input(N);//输入数据
        solve(N);//
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值