Codeforces 765F. Souvenirs

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

每次询问一个区间内任意两个数差值绝对值的最小值

不妨考虑一个位置i,他和哪些位置j(j<i)匹配可能更新区间的答案
这里只考虑a[i]>a[j]的情况,另一种同理
可能贡献的j一定是一个下降子,另外还有一个不那么显然的性质,就是真正有用的j序列的长度不超过log w,因为假设(j,i)可以产生贡献,下一个贡献的位置是j,j<j,那么真正有用的j需要满足两个条件 aiaj<aiaj,aiaj<ajaj,否则(j,j)的贡献就优于(j,i)
那么可以发现,aiaj每次至少减一半,所以有用的j不超过log个,我们可以直接找出这logj和i组成可能产生贡献的点对
然后每个询问在二维平面上就是询问一个矩形内最小的点这样的东西

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;

inline void down(int &a,const int &b){if(a>b)a=b;}
inline void read(int &x)
{
    char c; while(!((c=getchar())>='0'&&c<='9'));
    x=c-'0';
    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
int ch[10],chn;
inline void Output(int x)
{
    if(!x) { puts("0");return; }
    while(x) ch[++chn]=x%10,x/=10;
    while(chn) putchar('0'+ch[chn--]);
    putchar('\n');
}
const int maxn = 210000;
const int maxm = 1100000;

int n,m;
int a[maxn];
struct ct{int x;int *i;}s[maxn];
inline bool cmp(const ct x,const ct y){return x.x<y.x;}
int To[maxn],id;
void Trans()
{
    for(int i=1;i<=n;i++) s[i].x=a[i],s[i].i=&a[i];
    sort(s+1,s+n+1,cmp);
    for(int i=1,la=s[1].x-1;i<=n;la=s[i].x,i++)
    {
        if(la!=s[i].x) To[++id]=s[i].x;
        (*s[i].i)=id;
    }
}

struct segment
{
    int mx[maxn<<2];
    void init() { memset(mx,-1,sizeof mx); }
    void pushup(int x) { mx[x]=max(mx[x<<1],mx[x<<1|1]); }
    int loc,c;
    void upd(int x,const int l,const int r)
    {
        if(l==r) { mx[x]=c;return; }
        int mid=(l+r)>>1;
        if(loc<=mid) upd(x<<1,l,mid);
        else upd(x<<1|1,mid+1,r);
        pushup(x);
    }
    int lx,rx;
    int querymx(int x,const int l,const int r)
    {
        if(!x||rx<l||r<lx) return -1;
        if(lx<=l&&r<=rx) return mx[x];
        int mid=(l+r)>>1;
        return max(querymx(x<<1,l,mid),querymx(x<<1|1,mid+1,r));
    }
}seg;

struct segment2
{
    int seg[maxn<<2];
    int loc,lx,rx,c;
    void init() { memset(seg,63,sizeof seg); }
    void upd(int x,const int l,const int r)
    {
        if(rx<l||r<lx) return;
        if(lx<=l&&r<=rx) { down(seg[x],c);return; }
        int mid=l+r>>1;
        upd(x<<1,l,mid); upd(x<<1|1,mid+1,r);
    }
    int query(int x,const int l,const int r,int c)
    {
        down(c,seg[x]);
        if(l==r) return c;
        int mid=l+r>>1;
        if(loc<=mid) return query(x<<1,l,mid,c);
        else return query(x<<1|1,mid+1,r,c);
    }
}seg2;

int op[maxm],ans[maxm];
vector<int>V[maxn];

int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(a[i]); Trans();
    read(m);
    for(int i=1;i<=m;i++) 
    {
        int l,r; read(l); read(r);
        op[i]=l;
        V[r].push_back(i);
    }

    seg.init(); seg2.init();
    for(int i=1;i<=n;i++)
    {
        int las,l,r;

        las=0; r=1;
        while(1)
        {
            l=r,r=a[i];
            while(l<=r)
            {
                int mid=l+r>>1;
                if(To[mid]>=las) r=mid-1;
                else l=mid+1;
            }++r;
            seg.lx=r,seg.rx=a[i];
            int k=seg.querymx(1,1,n); if(k==-1) break;
            seg2.lx=1,seg2.rx=k,seg2.c=To[a[i]]-To[a[k]]; seg2.upd(1,1,n);
            if(las==To[a[i]]) break;
            las=To[a[k]]+(To[a[i]]-To[a[k]]+1)/2;
            if(las>To[a[i]]) break;
        }

        las=To[id]; l=id;
        while(1)
        {
            r=l,l=a[i];
            while(l<=r)
            {
                int mid=l+r>>1;
                if(To[mid]<=las) l=mid+1;
                else r=mid-1;
            }--l;
            seg.lx=a[i],seg.rx=l;
            int k=seg.querymx(1,1,n); if(k==-1) break;
            seg2.lx=1,seg2.rx=k,seg2.c=To[a[k]]-To[a[i]]; seg2.upd(1,1,n);
            if(las==To[a[i]]) break;
            las=To[a[k]]-(To[a[k]]-To[a[i]]+1)/2;
            if(las<To[a[i]]) break;
        }

        seg.loc=a[i],seg.c=i; seg.upd(1,1,n);

        for(int j=0;j<(int)V[i].size();j++)
        {
            int ii=V[i][j];
            seg2.loc=op[ii];
            ans[ii]=seg2.query(1,1,n,inf);
        }
    }
    for(int i=1;i<=m;i++) Output(ans[i]);

    return 0;
}
查看评论

【题解】codeforces765F Souvenirs

题目链接 题意:给定一个长度为n的数组与m个查询。第i个查询要求输出数组下标区间[li,ri]内的数之间的距离(差的绝对值)的最小值。 分析:离线处理查询。将查询区间按右端点从小到大排序,维护一个...
  • ZJZNKU
  • ZJZNKU
  • 2017-02-27 11:40:53
  • 150

[CF765F]Souvenirs

题目大意给定一个序列 多次询问一个区间最接近两个数的差值 最接近的两个数可以相同,但不能是同一个位置上的数。 允许离线强大线段树做法我们首先可以扫描线 从左到右扫,每次处理右端点在扫描线上的所...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2017-02-23 17:18:25
  • 527

【Codeforces Round #397】Codeforces 765F Souvenirs【解法一】

线段树
  • sdfzyhx
  • sdfzyhx
  • 2017-02-20 18:34:11
  • 310

Codeforces Round #397 Problem F. Souvenirs 解题报告

题目链接:Here! 题目大意:给你一个数组,每次给定一个区间,求 解题思路:由于只有询问,直接离线,按照左端点排序。然后建立一棵线段树,每一个节点维护一个set和当前的数的最小差值。从右到左依次更新...
  • baidu_35520981
  • baidu_35520981
  • 2017-02-18 11:44:41
  • 309

【Codeforces Round #397】Codeforces 765F Souvenirs【解法二】

线段树套平衡树
  • sdfzyhx
  • sdfzyhx
  • 2017-06-01 21:42:46
  • 192

hdoj2126Buy the souvenirs【01背包+不同组合记录】

Buy the souvenirs Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe...
  • R1986799047
  • R1986799047
  • 2015-08-10 08:28:15
  • 299

【HDU2126】【Buy the souvenirs】

Buy the souvenirs Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other...
  • u013200703
  • u013200703
  • 2015-07-30 20:27:46
  • 277

HDU 2126 Buy the souvenirs

Buy the souvenirs Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe...
  • hqu_fritz
  • hqu_fritz
  • 2014-06-18 23:59:58
  • 717

HDU2126:Buy the souvenirs(01)

Problem Description When the winter holiday comes, a lot of people will have a trip. Generally, t...
  • libin56842
  • libin56842
  • 2014-11-30 10:48:41
  • 1326

Codeforces Gym 100753J Souvenirs

题目链接戳这里。 题目大意:你出去旅游,该国家只有金币和银币两种货币,金币和银币有一个汇率,这里的商人的找零方式是把银币分为一袋子一袋子,他只能一袋子一袋子的找零,商人分为三种,傻帽:包数按...
  • szh_0808
  • szh_0808
  • 2017-10-02 17:10:42
  • 62
    个人资料
    持之以恒
    等级:
    访问量: 15万+
    积分: 6339
    排名: 4721