关闭

poj 3419 Difference Is Beautiful (dp+二分+RMQ或者dp+离线线段树)

271人阅读 评论(0) 收藏 举报
分类:

Difference Is Beautiful

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 2141 Accepted: 672
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 [L, R] of the turnover sequence, can you help him?

Input

The first line of the input contains two integers N and M. N is the number of companies. M is the number of queries. (1 ≤ N, M ≤ 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: L, R (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 [L, R]  

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.
Source

POJ Monthly–2007.10.06, SHOIT@ZSU


这题十分的经典,虽然我一直不是太会做这种数据结构题,看来接下去需要恶补一发数据结构和dp
这题有两种方法,一种是网上很多的dp+二分+RMQ,还有一种是学长想出来的离线线段树,因为很多区间问题都能用离线的方法解决呢,能不能用莫队我还没有想出来,而且这题20W的数据量莫队估计是过不去的

1.dp+二分+RMQ:dp就是处理dp[i]表示i位置最远能到哪个位置,然后这一段里面没有重复,非常简单,扫两遍就行了,然后考虑到一个性质,就是dp[i]是单调不减的,很明显吧,然后把idp[i]存进RMQ里,这样就能做到O(1)的查询了,然后对于每次询问的一个区间[L,R],考虑这个区间里的i,有些dp[i]肯定是超出L的,还有些idp[i]是在区间里的,所以根据单调性,可以二分找到这个临界值r,然后答案就是max(rL+1,RMQ(r+1,R))


代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;
#define   MAX           200005
#define   MAXN          2000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
//const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x){
    char c;
    while((c=getchar())<'0' || c>'9');
    x=c-'0';
    while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

int a[MAX];
int vis[MAXN];
int dp[MAX];
int n,m;
int d[MAX][25];
void RMQ_init(){
    for(int i=1;i<=n;i++) d[i][0]=i-dp[i];
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
        }
    }
}

int RMQ(int L,int R){
    if(L>R) return 0;
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    return max(d[L][k],d[R-(1<<k)+1][k]);
}

int main(){
    //freopen("input.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n>>m;
    mem(vis,0);mem(dp,0);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=1000000;
    for(int i=1;i<=n;i++){
        if(!vis[a[i]]) vis[a[i]]=i,dp[i]=0;
        else{
            dp[i]=vis[a[i]];
            vis[a[i]]=i;
        }
    }
    for(int i=1;i<=n;i++){
        dp[i]=max(dp[i],dp[i-1]);
    }
    RMQ_init();
    while(m--){
        int aa,bb;
        scanf("%d%d",&aa,&bb);
        aa++,bb++;
        int l=aa,r=bb;
        while(l<=r){
            int mid=(l+r)/2;
            if(dp[mid]>=aa) r=mid-1;
            else l=mid+1;
        }
        cout<<max(r-aa+1,RMQ(l,bb))<<endl;
    }
    return 0;
}

2.dp+离线线段树:dp的方法和上面一样,然后就是离线区间处理,重点在于区间怎么排序,线段树维护什么值。这方面我比较弱,参考学长的,按照区间的右端点排序,然后线段树维护什么呢,对于一个位置i,把区间[dp[i]+1,i]里都加1,这样表示区间里这些位置,被多少个(不重复出现的串)包含在里面,这里不好表述,需要自己想一下,然后查询的时候就是query(l,r),查询这个区间里,哪一个点被最多的[dp[i]+1,i]这样的区间覆盖,这样也是考虑到dp[i]是单调不减的性质呢其实,看来我离线还是太渣了otz


代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;
#define   MAX           200005
#define   MAXN          2000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
//const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x){
    char c;
    while((c=getchar())<'0' || c>'9');
    x=c-'0';
    while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

int a[MAX];
int vis[MAXN];
int dp[MAX];
int n,m;
int maxv[MAX<<2];
int add[MAX<<2];
struct que{
    int l,r,id,ans;
}p[MAX];
bool cmp1(que a,que b){
    return a.r<b.r;
}
bool cmp2(que a,que b){
    return a.id<b.id;
}
void pushup(int rt){
    maxv[rt]=max(maxv[lrt],maxv[rrt]);
}

void pushdown(int rt){
    if(add[rt]){
        add[lrt]+=add[rt];
        add[rrt]+=add[rt];
        maxv[rrt]+=add[rt];
        maxv[lrt]+=add[rt];
        add[rt]=0;
    }
}

void build(int l,int r,int rt){
    maxv[rt]=add[rt]=0;
    if(l==r) return ;
    middle;
    build(lson);
    build(rson);
}

void update(int l,int r,int rt,int L,int R,int d){
    if(L<=l&&r<=R){
        add[rt]+=d;
        maxv[rt]+=d;
        return ;
    }
    pushdown(rt);
    middle;
    if(L<=m) update(lson,L,R,d);
    if(R>m) update(rson,L,R,d);
    pushup(rt);
}

int query(int l,int r,int rt,int L,int R){
    if(L<=l&&r<=R) return maxv[rt];
    middle;
    pushdown(rt);
    int ans=0;
    if(L<=m) ans=max(ans,query(lson,L,R));
    if(R>m) ans=max(ans,query(rson,L,R));
    pushup(rt);
    return ans;
}

int main(){
    //freopen("input.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>n>>m;
    mem(vis,0);mem(dp,0);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=1000000;
    for(int i=1;i<=n;i++){
        if(!vis[a[i]]) vis[a[i]]=i,dp[i]=0;
        else{
            dp[i]=vis[a[i]];
            vis[a[i]]=i;
        }
    }
    for(int i=1;i<=n;i++){
        dp[i]=max(dp[i],dp[i-1]);
    }
    build(1,n,1);
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        x++,y++;
        p[i]=(que){x,y,i};
    }
    sort(p,p+m,cmp1);
    int tmp=1;
    for(int i=0;i<m;i++){
        while(tmp<=p[i].r){
            update(1,n,1,dp[tmp]+1,tmp,1);
            tmp++;
        }
        p[i].ans=query(1,n,1,p[i].l,p[i].r);
    }
    sort(p,p+m,cmp2);
    for(int i=0;i<m;i++) printf("%d\n",p[i].ans);
    return 0;
}
0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:118571次
    • 积分:4220
    • 等级:
    • 排名:第7189名
    • 原创:314篇
    • 转载:5篇
    • 译文:0篇
    • 评论:45条
    最新评论