$n \leq 100000$的数列给$m \leq 300000$的询问,每次问一个区间里选两个数差的最小值。数字$\leq 1e9$。

根号算法:

无脑莫队加个平衡树或者权值线段树来查前驱后继是$n \sqrt{n} log_2n$的。

如果只有删除可以用链表实现,所以想办法去掉插入操作。对左端点$l$在一块$[x,y]$中的询问,可以先用链表处理出所有$i>y$的$a_i$在$[y+1,i-1]$的前驱后继,接下来只要查$[l,y]$间的数字在$[y+1,r]$中的前驱后继即可。这时把询问的$r$从大到小排序,回答每个询问的时候,左边直接删除至$y$回答询问,然后暴力把链表改回去即可。这样$m \sqrt{n}$。

数据结构:

看看一个$i$会和哪些数搞起来对答案产生贡献。先找$j>i,a_j \geq a_i$的,$a_j<a_i$的同理。若找$a_j \geq a_i$,那么找到的数字将是个递减数列。如果数据随机,这递减数列是$log_2Max$级别长度的。但专门构造数据可以卡掉。

假如我们已经找了个$j$,要找下一个和$i$搭配能产生贡献的数,假设是$a_k,k>j$,那么有$a_i \leq a_k \leq a_j$,就是上面说的递减数列。除此之外,$a_k-a_i<a_j-a_k$,这啥?因为如果不满足他,$a_j$和$a_k$将比$a_i$和$a_k$优,$i$和$k$又远又大就没用了!!这样有贡献的点对就是$nlog_2Max$级别了,加个二维数点就可以$log^2$通过。

怎么找点对,可以用主席树,也可以把$a_i$排序加入线段树,在线段树上二分得到。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 //#include<time.h>
  5 //#include<complex>
  6 //#include<queue>
  7 #include<algorithm>
  8 #include<stdlib.h>
  9 using namespace std;
 10
 11 #define LL long long
 12 int qread()
 13 {
 14     char c; int s=0; while ((c=getchar())<'0' || c>'9');
 15     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
 16 }
 17
 18 //Pay attention to '-' and LL of qread!!!!
 19
 20 int n,lq;
 21 #define maxn 200011
 22 #define maxm 1000011
 23 int a[maxn];
 24 struct Poi{int v,id; bool operator < (const Poi &b) const {return v>b.v;}}p[maxn];
 25
 26 struct Ques{int x,y,v; bool operator < (const Ques &b) const {return x>b.x;}}q[maxm],aa[maxn*60];
 27 int la=0;
 28
 29 struct SMT
 30 {
 31     struct Node
 32     {
 33         int ls,rs;
 34         int Max,Min;
 35     }a[maxn<<1];
 36     int size,n;
 37     void up(int x)
 38     {
 39         Node &b=a[x],&p=a[a[x].ls],&q=a[a[x].rs];
 40         b.Max=max(p.Max,q.Max); b.Min=min(p.Min,q.Min);
 41     }
 42     void build(int &x,int L,int R)
 43     {
 44         x=++size;
 45         if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=-2e9; a[x].Min=2e9; return;}
 46         int mid=(L+R)>>1;
 47         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x);
 48     }
 49     void build() {int x; build(x,1,n);}
 50     void clear(int m) {n=m; size=0; build();}
 51     int ql,qr,v;
 52     void Modify(int x,int L,int R)
 53     {
 54         if (L==R) {a[x].Max=a[x].Min=v; return;}
 55         int mid=(L+R)>>1;
 56         if (ql<=mid) Modify(a[x].ls,L,mid); else Modify(a[x].rs,mid+1,R);
 57         up(x);
 58     }
 59     void modify(int pos,int v) {ql=pos; this->v=v; Modify(1,1,n);}
 60     int Query1(int x,int L,int R)
 61     {
 62         if (L==R) {return (L>=ql && a[x].Min<=v)?L:0;}
 63         int mid=(L+R)>>1;
 64         if (ql>mid) return Query1(a[x].rs,mid+1,R);
 65         if (ql<=L)
 66         {
 67             if (a[a[x].ls].Min<=v) return Query1(a[x].ls,L,mid);
 68             if (a[a[x].rs].Min<=v) return Query1(a[x].rs,mid+1,R);
 69             return 0;
 70         }
 71         int tmp=Query1(a[x].ls,L,mid);
 72         if (tmp) return tmp;
 73         if (a[a[x].rs].Min<=v) return Query1(a[x].rs,mid+1,R);
 74         return 0;
 75     }
 76     int query1(int pos,int v) {if (pos>n) return 0; ql=pos; this->v=v; return Query1(1,1,n);}
 77     int Query2(int x,int L,int R)
 78     {
 79         if (L==R) {return (L>=ql && a[x].Max>=v)?L:0;}
 80         int mid=(L+R)>>1;
 81         if (ql>mid) return Query2(a[x].rs,mid+1,R);
 82         if (ql<=L)
 83         {
 84             if (a[a[x].ls].Max>=v) return Query2(a[x].ls,L,mid);
 85             if (a[a[x].rs].Max>=v) return Query2(a[x].rs,mid+1,R);
 86             return 0;
 87         }
 88         int tmp=Query2(a[x].ls,L,mid);
 89         if (tmp) return tmp;
 90         if (a[a[x].rs].Max>=v) return Query2(a[x].rs,mid+1,R);
 91         return 0;
 92     }
 93     int query2(int pos,int v) {if (pos>n) return 0; ql=pos; this->v=v; return Query2(1,1,n);}
 94 }smt;
 95
 96 struct BIT
 97 {
 98     int a[maxn],n;
 99     void clear(int m) {n=m; for (int i=1;i<=n;i++) a[i]=2e9;}
100     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]=min(a[x],v);}
101     int query(int x) {int ans=2e9; for (;x;x-=x&-x) ans=min(ans,a[x]); return ans;}
102 }bit;
103
104 int ans[maxm];
105 int main()
106 {
107     n=qread();
108     for (int i=1;i<=n;i++) a[i]=qread();
109     lq=qread();
110     for (int i=1;i<=lq;i++) q[i].x=qread(),q[i].y=qread(),q[i].v=i;
111
112     for (int i=1;i<=n;i++) p[p[i].id=i].v=a[i];
113     sort(p+1,p+1+n);
114     smt.clear(n);
115     for (int i=1;i<=n;i++)
116     {
117         int id=p[i].id,v=p[i].v;
118         smt.modify(id,v);
119         int wow=2e9+1,tmp,now=id+1;
120         while (wow!=v && (tmp=smt.query1(now,(wow+0ll+v)>>1))) wow=a[tmp],aa[++la]=(Ques){id,tmp,wow-v},now=tmp+1;
121     }
122
123     smt.clear(n);
124     for (int i=n;i;i--)
125     {
126         int id=p[i].id,v=p[i].v;
127         smt.modify(id,v);
128         int wow=-1e9,tmp,now=id+1;
129         while (wow!=v && (tmp=smt.query2(now,(wow+1ll+v)>>1))) wow=a[tmp],aa[++la]=(Ques){id,tmp,v-wow},now=tmp+1;
130     }
131
132     sort(aa+1,aa+1+la); sort(q+1,q+1+lq);
133     bit.clear(n);
134     for (int i=1,j=1;i<=lq;i++)
135     {
136         while (j<=la && aa[j].x>=q[i].x) bit.add(aa[j].y,aa[j].v),j++;
137         ans[q[i].v]=bit.query(q[i].y);
138     }
139     for (int i=1;i<=lq;i++) printf("%d\n",ans[i]);
140     return 0;
141 }

View Code

转载于:https://www.cnblogs.com/Blue233333/p/8871677.html

Codeforces765F. Souvenirs相关推荐

  1. codeforces765F Souvenirs

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. 【题解】codeforces765F Souvenirs

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

  3. CF765F Souvenirs 解题报告

    CF765F Souvenirs 题意翻译 给出\(n(2 \le n \le 10^5 )\) ,一个长为\(n\)的序列\(a(0 \le a_i \le 10^9 )\). 给出\(m(1\le ...

  4. CF765F Souvenirs(势能线段树)

    CF765F Souvenirs problem solution code problem 题目链接 solution 这个势能线段树简直是太巧妙了!!!( ఠൠఠ )ノ 将询问按右端点升序离线下来 ...

  5. # CF765F Souvenirs

    CF765F Souvenirs 将询问按照右端点记录下来. 我们考虑从左向右处理每一个 aia_iai​ 对它前面的所有区间 [l,i](l∈[1,i])[l, i] ~~(l \in [1,i]) ...

  6. hdu2126 Buy the souvenirs 01背包变形 dp

    链接:点我 题意:n个物品,m元钱,每个物品最多买一次,问最多可以买几件物品,并且输出方案数.加一维表示已经买几件物品. 我这里用了一个数组dp[v][2] ,dp[v][0] 储存原本要记录的 dp ...

  7. 【ICPC-283】hdu 2126 Buy the souvenirs(二维0/1背包)

    点击打开链接hdu2126 思路: 二维0/1背包 分析: 1 题目给定n个物品的价钱和m的钱,问最多能买到的物品数有几种方案. 2 很明显就可以写出状态转移方程dp[i][j][k]表示的是前i个物 ...

  8. codeforces Round 21 808E. Selling Souvenirs 【dp好题】

    codeforces Round 21 808E. Selling Souvenirs [dp好题] E. Selling Souvenirs time limit per test 2 second ...

  9. Educational Codeforces Round 21 E. Selling Souvenirs(背包)

    题目:http://codeforces.com/contest/808/problem/E 题目大意: 有n个物品,背包容量为m. 每个物品只会有1,2,3个单位占有空间,价值为c. 现在问如何可以 ...

最新文章

  1. linux后台执行命令:amp;与nohup的用法
  2. python gamma矫正
  3. 几种常用的Java数据源解决方案
  4. 写给那些正奔三的80后[转]
  5. 【转载】防范SQL注入式攻击
  6. nginx httpgzip模块
  7. html、css 【珍藏】
  8. 【线上直播】:5G时代VR+8K直播 刷新你的视界认知
  9. 12对胸椎对应体表标志_铁路信号之信号表示器及标志(三)
  10. 关于鼓励软件产业和集成电路产业发展有关税收政策问题的通知
  11. 学做‘视频剪辑’攻略
  12. python xy 2.7下载_pythonxy 安装
  13. 浅谈对社会工程学的认识
  14. 航模舵机控制原理详解
  15. Python数据分析 笔记4(matplotlib库)
  16. WM安装windows7超详细教程
  17. 计算机磁盘管理 移动硬盘创建盘符,电脑中插入移动硬盘后无法显示分区盘符如何解决...
  18. 通达信l2行情接口怎么用?
  19. #C语言学习笔记#猴子偷桃问题
  20. fsQCA+NCA方法的软件操作及注意事项、论文实证分析部分的写作范式

热门文章

  1. ArcGIS聚合容差修正两个shapefile 之间的数字化错误
  2. C#中使用EntityFramework出现报错问题
  3. error LNK2001: 无法解析的外部符号 解决方法
  4. 如何转换音频格式简单图文教程
  5. STM32的复位电路、ISP一键下载原理
  6. 【pgsql】使用<foreach></foreach>处理数组或对象数组时的循环操作
  7. matlab中vec2ind,MATLAB中的ind2vec和vec2ind函数
  8. MATLAB常用命令及函数大全(字母顺序)
  9. postgresql 随笔
  10. 2021-2027全球及中国G Suite教学资源软件行业研究及十四五规划分析报告