poj 3419 Difference Is Beautiful 离线线段树

Difference Is Beautiful
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 2102 Accepted: 656

Description

Mr. Flower's business is growing much faster than originally planned. He has now become the CEO of a world-famous beef corporation. However, the boss never lives a casual life because he should take charge of the subsidiary scattered all over the world. Every year, Mr. Flower needs to analyze the performance reports of these subsidiary companies.

Mr. Flower has N companies, and he numbered them with 0 to N – 1. All of the companies will give Mr. Flower a report about the development each year. Among all of the tedious data, only one thing draws Mr. Flower's attention – the turnover. Turnover of a company can be represented as an integer Pi: positive one represents the amount of profit-making while negative for loss-making.

In fact, Mr. Flower will not be angry with the companies running under deficit. He thinks these companies have a large room for future development. What dissatisfy him are those companies who created the same turnover. Because in his eyes, keeping more than one companies of the same turnover is not necessary.

Now we know the annual turnover of all companies (an integer sequence Pi, the ith represents the turnover of the ith company this year.). We say a number sequence is perfect if all of its numbers are different from each other. Mr. Flower wants to know the length of the longest consecutive perfect sequence in a certain interval [LR] of the turnover sequence, can you help him?

Input

The first line of the input contains two integers N and MN is the number of companies. M is the number of queries. (1 ≤ NM ≤ 200000). The second line contains N integer numbers not exceeding 106 by their absolute values. The ith of them represents the turnover of the ith company this year. The following M lines contain query descriptions, each description consists of two numbers: LR (0 ≤ L ≤ R ≤ N – 1) and represents the interval that Mr. Flower concerned.

Output

The output contains M lines. For each query, output the length of the longest consecutive perfect sequence between [LR]  

Sample Input

9 2
2 5 4 1 2 3 6 2 4
0 8
2 6

Sample Output

6
5

Hint

The longest perfect sequence of the first query in the sample input is '5 4 1 2 3 6', so the answer for this query is 6.


题意很简单,就是问一个区间内最长的连续无重复元素的子序列的长度,有多组询问。


这题是在叉姐的魔法训练上看到的,我用的方法和正解不同,我是用离线线段树做的,有兴趣的小伙伴们也可以去看看其他的做法,也是很巧妙的。

这题当我看到数据量之后,而且是多组询问,我自然的就想到了用离线线段树来做,可能是最近这一类的题目做多了吧,现在看什么都像。。。

我们线段树的每个节点的意义就是以这个点作为起点,满足条件的最长的区间长度,首先我们预处理出每个数字左边第一个和他相同的数字的位置,这个因为数据量就1e6,所以很简单,不会的就去看我下面的代码好了,然后我们把所有的询问都读进来,再按照询问的右边界r从小到大排序。然后对于每组询问,我们把比右区间r小的节点都插入到线段树里并更新其他的节点,怎么插入呢?对于位于第i位的数字ai,他左边第一个和他相同的数字的位置是l[i],那么就把l[i]+1到i的所有节点都加1,因为这个区间里的所有数字都和ai不相同,所以最长区间都要加上ai,所以加1。对于第i+1个数,我们不是更新l[i+1]+1到i+1的所有节点,而是更新max(l[i],l[i+1])+1到i+1的所有区间,因为当l[i+1]比l[i]小的时候,因为a[i]和a[l[i]]相同,所以对于l[i+1]到l[i]这个区间里的节点已经不能再更新了,他们的最大长度已经确定了,所以我们在更新的时候要维护一个最大的l[i],然后对于每一组询问,就是一个线段树求区间最大值过程了。具体的细节就看代码就好了。。。


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

const int maxn = 2e5+10;
int ma[maxn*4],b[maxn],l[maxn],add[maxn*4];
const int inf = 1e6+2;
int c[2000010];
struct aa{
    int l,r,id,ans;
}a[maxn];
int n,m;

bool cmp(aa i,aa j){
    return i.r<j.r;
}

bool cmp1(aa i,aa j){
    return i.id<j.id;
}

void pushdown(int rt){
    if(add[rt]){
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        ma[rt<<1]+=add[rt];
        ma[rt<<1|1]+=add[rt];
        add[rt]=0;
    }
}

void update(int L,int R,int c,int l,int r,int rt){
    if(l>=L&&r<=R){
        add[rt]+=c;
        ma[rt]+=c;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)/2;
    if(mid>=L) update(L,R,c,l,mid,rt<<1);
    if(mid+1<=R) update(L,R,c,mid+1,r,rt<<1|1);
    ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
}

int query(int L,int R,int l,int r,int rt){
    if(l>=L && r<=R)
        return ma[rt];
    pushdown(rt);
    int ans=0,mid=(l+r)/2;
    if(mid>=L) ans=max(ans,query(L,R,l,mid,rt<<1));
    if(mid+1<=R) ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
    return ans;
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(cin>>n>>m){
        memset(add,0,sizeof(add));
        memset(ma,0,sizeof(ma));
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        for(int i=1;i<=n;i++){
            l[i]=c[b[i]+inf];
            c[b[i]+inf]=i;
        }
        for(int i=0;i<m;i++){
            scanf("%d %d",&a[i].l,&a[i].r);
            a[i].l++;
            a[i].r++;
            a[i].id=i;
        }
        sort(a,a+m,cmp);
        int cnt=1,maxx=0;
        for(int i=0;i<m;i++){
            while(cnt<=a[i].r){
                maxx=max(maxx,l[cnt]);
                update(maxx+1,cnt,1,1,n,1);
                cnt++;
            }
            a[i].ans=query(a[i].l,a[i].r,1,n,1);
        }
        sort(a,a+m,cmp1);
        for(int i=0;i<m;i++)
            printf("%d\n",a[i].ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值