码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-5172-GTY's gay friends-线段树单点更新

时间:2015-08-04 21:11:56      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:hdu5172   gtys gay friends   线段树单点更新   bestcoder#29   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172

题意:给出n个数,m个询问,问你[l,r]区间内是否为1到r-l+1的全排列。 大小很容易我们通过记录前缀和很容易求出来,但是关键是去重。 考虑线段树做法,我们记录每个点的靠左最近的相同元素的位置,然后求 整个区间的最大值(即最大的前驱)如果小于l,即满足条件,输出YES。

好吧,其实这个题目我是搜的RMQ算法出来的,因为我想练一下RMQ算法,所以我就看了一下别人的博客,自己也写了一下,结果死活MLE。。。

好吧,我仔细看了一下,1000000的数据量用RMQ开一个二维数组1000000*20,显然会超内存。。。

结果我不得不老老实实的滚回去用线段树写了。。。orz....

RMQ的MLE代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define LL long long
#define inf 1<<30
#define sf(a) scanf("%d",&a);
#define CLEAR(a,b) memset(a,b,sizeof(a))
using namespace std;
/*
    TLE...显然超内存;
*/
const int N=1000005;
int n,m,a,b;
int num[N],pre[N];
int dp[N][21];
int sum[N];
void ST(int len)
{
    for(int i=1;i<=n;i++) dp[i][0]=num[i];
    for(int j=1;1<<j < n;j++){
        for(int i=1;i+(1<<j)-1<n;i++){
            dp[i][j]=max(dp[i][j-1],dp[i+1<<(j-1)][j-1]);
        }
    }
}
int rmq(int s,int v)
{
    int k=(int)(log(v-s+1)*1.0/log(2.0));
    return max(dp[s][k],dp[v-1<<k+1][k]);
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        CLEAR(pre,0);
        CLEAR(sum,0);
        for(int i=1;i<=n;i++){
            sf(a);
            sum[i]+=sum[i-1]+a;
            num[i]=pre[a];
            pre[a]=i;
        }
        ST(n);
        while(m--){
            sf(a);sf(b);
            double tmp=(b-a+2)*(b-a+1)*1.0/2.0;
            if(tmp!=sum[b]-sum[a-1]){
                //cout<<tmp<<' '<<sum[b]-sum[a-1]<<' ';
                printf("NO\n");
                continue;
            }else{
                if(rmq(a,b)<a) printf("YES\n");
                else printf("NO\n");
            }
        }
    }
    return 0;
}

 

线段树AC代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define LL long long
#define inf 1<<30
#define s(a) scanf("%d",&a)
#define CLEAR(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=1000005;
int n,m,a,b;
int pre[N],sum[N];  //  sum存总和,pre定位该数字上一次出现的位置;
struct node
{
    int l,r;
    int pre;    //  用线段树维护最近一个重复的数字;
}node[N<<2];
void PushUp(int rt)
{
    node[rt].pre=max(node[rt<<1].pre,node[rt<<1|1].pre);
}
void build(int l,int r,int rt)
{
    node[rt].l=l;
    node[rt].r=r;
    node[rt].pre=0;
    if(l!=r){
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    }
}
void Insert(int v,int p,int rt)
{
    int ll=node[rt].l,rr=node[rt].r;
    if(ll==rr&&p==ll){
        node[rt].pre=pre[v];
        return;
    }
    int mid=(ll+rr)>>1;
    if(p<=mid) Insert(v,p,rt<<1);
    else Insert(v,p,rt<<1|1);
    PushUp(rt);
}
int query(int l,int r,int rt)
{
    int ll=node[rt].l,rr=node[rt].r;
    if(ll==l&&rr==r){
        return node[rt].pre;
    }
    int mid=(ll+rr)>>1;
    if(r<=mid) return query(l,r,rt<<1);
    else if(l>mid) return query(l,r,rt<<1|1);
    else return max(query(l,mid,rt<<1),query(mid+1,r,rt<<1|1));
}
int main()
{
    while(~s(n)){
        s(m);
        CLEAR(pre,0);
        CLEAR(sum,0);
        build(1,n,1);
        for(int i=1;i<=n;i++){
            s(a);
            sum[i]+=sum[i-1]+a;
            Insert(a,i,1);
            pre[a]=i;
        }
        while(m--){
            s(a);s(b);
            int tmp=(b-a+2)*(b-a+1)*1.0/2.0;    //  如果是全排列那么最后的和必然符合这个公式;
            if(sum[b]-sum[a-1]!=tmp){
                printf("NO\n");
                continue;
            }else{
                if(query(a,b,1)<a) printf("YES\n"); //  查询该区间最近一个重复的数字出现的位置,如果比a小,那就说明这个区间没有出现过重复的数字;
                else printf("NO\n");
            }
        }
    }
    return 0;
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU-5172-GTY's gay friends-线段树单点更新

标签:hdu5172   gtys gay friends   线段树单点更新   bestcoder#29   

原文地址:http://blog.csdn.net/wlxsq/article/details/47281165

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!