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

XTU 1205 Range

时间:2014-08-31 09:12:40      阅读:417      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   os   io   for   div   问题   log   

还是五月湘潭赛的题目,当时就是因为我坑。。。连个银牌都没拿到,擦。

这个题目枚举区间是不可能的,明显是要考虑每个数对全局的影响,即找到每个数最左和最右能满足是最大的位置 以及 最小的时候,相乘即为该数字影响的区间总数。当时想到的是用线段树,建树的时候求出最大和最小值,然后在每个数往里面搜索,比赛的时候敲挫了,那个时候真的线段树写的很挫,而且没考虑过一个问题,就是相同的时候怎么办,按刚刚的算法,会算重复的,所以一个好的方法是如果有相同的,往左搜的时候搜到等于该数值的时候停止,往右搜的时候搜到大于该数值的时候停止(求最大的时候),求最小的时候也是一样的处理

然后搜左边的时候优先走右子树,右子树没有 再找左子树。。同理右边先搜左孩子,没有再搜右孩子,注意些细节以及可以剪剪枝。

线段树写这个题目其实很费力,有种更好的方法用桟来做,栈在求最大最小的时候往往很给力,像这个题目,我比如在求左边最大的时候,我当前数,如果碰到栈顶数比它大于等于的,就直接停止了,入桟,否则就一直pop下去,直到遇到比它大于等于的或者桟空,这个时候得到了左边区间最大,并且把当前值放进去,因为我只保留左边区间离下个数最近的最大的数即可,如果连这个数都不能阻挡下一个数,那之前被pop掉的肯定也阻挡不了,所以扫一遍即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define LL __int64
using namespace std;
const int N = 100010;
int dmin[N<<2],dmax[N<<2];
int A[N];
int n;
void build(int rt,int l,int r)
{
    if (l>=r){
        dmin[rt]=A[l];
        dmax[rt]=A[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    dmax[rt]=max(dmax[rt<<1],dmax[rt<<1|1]);
    dmin[rt]=min(dmin[rt<<1],dmin[rt<<1|1]);
}
int query1(int L,int R,int val,int rt,int l,int r)
{
    if (L>R) return R;
    if (l>=r){
        if(l>=L &&l<=R && A[l]>=val){
            return l;
        }
        else return 0;
    }
    int mid=(l+r)>>1;
    if (R<=mid){
        if (dmax[rt<<1]>=val)
        return query1(L,R,val,lson);
        else return 0;
    }
    int ret=0;
    if (dmax[rt<<1|1]>=val){
        ret=query1(L,R,val,rson);
    }
    if (ret>0) return ret;
    if (dmax[rt<<1]>=val)
    return query1(L,R,val,lson);
    else return 0;
}
int query2(int L,int R,int val,int rt,int l,int r)
{
    if (L>R) return L;
    if (l>=r){
        if (l>=L && l<=R && A[l]>=val){
            return l;
        }
        else return n+1;
    }
    int mid=(l+r)>>1;
    if (L>mid){
        if (dmax[rt<<1|1]>=val)
        return query2(L,R,val,rson);
        else return n+1;
    }
    int ret=n+1;
    if (dmax[rt<<1]>=val){
        ret=query2(L,R,val,lson);
    }
    if (ret<n+1) return ret;
    if (dmax[rt<<1|1]>=val)
    return query2(L,R,val,rson);
    else return n+1;
}
int query3(int L,int R,int val,int rt,int l,int r)
{
    if (L>R) return R;
    if (l>=r){
        if (L<=l && l<=R && A[l]<=val){
            return l;
        }
        else return 0;
    }
    int mid=(l+r)>>1;

    if (R<=mid){
        if (dmin[rt<<1]<=val){
            return query3(L,R,val,lson);
        }
        else return 0;
    }
    int ret=0;
    if (dmin[rt<<1|1]<=val) ret=query3(L,R,val,rson);
    if (ret>0) return ret;
    if (dmin[rt<<1]<=val)
    return query3(L,R,val,lson);
    else return 0;
}
int query4(int L,int R,int val,int rt,int l,int r)
{
    if (L>R) return L;
    if (l>=r){
        if (L<=l && r<=R && A[l]<=val){
            return l;
        }
        else return n+1;
    }
    int mid=(l+r)>>1;
    if (L>mid){
        if (dmin[rt<<1|1]<=val){
            return query4(L,R,val,rson);
        }
        else return n+1;
    }
    int ret=n+1;
    if (dmin[rt<<1]<=val){
        ret=query4(L,R,val,lson);
    }
    if (ret<n+1) return ret;
    else
    if (dmin[rt<<1|1]<=val) return query4(L,R,val,rson);
    return n+1;
}
int main()
{
    int t;
    int kase=0;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&A[i]);
        build(1,1,n);
        LL sum=0;
        for (int i=1;i<=n;i++){
            int l1=query1(1,i-1,A[i],1,1,n);
            int l2=query2(i+1,n,A[i]+1,1,1,n);
            int l3=query3(1,i-1,A[i],1,1,n);
            int l4=query4(i+1,n,A[i]-1,1,1,n);
            //cout<<"Test "<<i<<endl;
           // cout<<l1<<" "<<l2<<" "<<l3<<" "<<l4<<endl;
            sum+=(LL)(i-l1)*(LL)(l2-i)*(LL)A[i];
            sum-=(LL)(i-l3)*(LL)(l4-i)*(LL)A[i];
        }
        sum+=(LL)n*(n+1)/2;
        printf("Case %d: %I64d\n",++kase,sum);
    }
    return 0;
}

 

XTU 1205 Range

标签:style   blog   color   os   io   for   div   问题   log   

原文地址:http://www.cnblogs.com/kkrisen/p/3947234.html

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