Problem

查询区间第k大,但保证区间不互相包含(可以相交)

Solution

只需要对每个区间左端点进行排序,那它们的右端点必定单调递增,不然会出现区间包含的情况。

所以我们暴力对下一个区间加上这个区间没有的点,删去下个区间没有的点。

因为每个点最多被加入,删除1次,所以时间复杂度为O(nlogn)

Notice

当相邻两段区间不相交时,那么我们要先加入点,在删去点。

Code

非旋转Treap

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 100000, M = 50000;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
int point = 0, T[N + 5], root, ans[M + 5];
struct Node
{
int left, right, ask, id;
}Q[M + 5];
struct node
{
int Size[N + 5], Val[N + 5], Level[N + 5], Son[2][N + 5];
inline void up(int u)
{
Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + 1;
}
int Newnode(int v)
{
int u = ++point;
Val[u] = v, Level[u] = rand();
Size[u] = 1, Son[0][u] = Son[1][u] = 0;
return u;
}
int Merge(int X, int Y)
{
if (X * Y == 0) return X + Y;
if (Level[X] < Level[Y])
{
Son[1][X] = Merge(Son[1][X], Y);
up(X); return X;
}
else
{
Son[0][Y] = Merge(X, Son[0][Y]);
up(Y); return Y;
}
}
void Split(int u, int t, int &x, int &y)
{
if (!u)
{
x = y = 0;
return;
}
if (Val[u] <= t) x = u, Split(Son[1][u], t, Son[1][u], y);
else y = u, Split(Son[0][u], t, x, Son[0][u]);
up(u);
}
void Build(int l, int r)
{
int last, s[N + 5], top = 0;
rep(i, l, r)
{
int u = Newnode(T[i]);
last = 0;
while (top && Level[s[top]] > Level[u])
{
up(s[top]);
last = s[top--];
}
if (top) Son[1][s[top]] = u;
Son[0][u] = last;
s[++top] = u;
}
while (top) up(s[top--]);
root = s[1];
} int Find_num(int u, int t)
{
if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
else if (t <= Size[Son[0][u]] + 1) return u;
else return Find_num(Son[1][u], t - Size[Son[0][u]] - 1);
}
void Insert(int v)
{
int t = Newnode(v), x, y;
Split(root, v, x, y);
root = Merge(Merge(x, t), y);
}
void Delete(int v)
{
int x, y, z;
Split(root, v, x, z), Split(x, v - 1, x, y);
root = Merge(Merge(x, Merge(Son[0][y], Son[1][y])), z);
}
}Treap;
int cmp(Node X, Node Y)
{
return X.left < Y.left || (X.left == Y.left && X.right < Y.right);
}
int sqz()
{
int n = read(), m = read();
rep(i, 1, n) T[i] = read();
rep(i, 1, m) Q[i].left = read(), Q[i].right = read(), Q[i].ask = read(), Q[i].id = i;
sort(Q + 1, Q + m + 1, cmp);
rep(i, Q[1].left, Q[1].right) Treap.Insert(T[i]);
ans[Q[1].id] = Treap.Val[Treap.Find_num(root, Q[1].ask)];
rep(i, 2, m)
{
rep(j, Q[i - 1].right + 1, Q[i].right) Treap.Insert(T[j]);
rep(j, Q[i - 1].left, Q[i].left - 1) Treap.Delete(T[j]);
ans[Q[i].id] = Treap.Val[Treap.Find_num(root, Q[i].ask)];
}
rep(i, 1, m) printf("%d\n", ans[i]);
return 0;
}

旋转Treap

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, N = 100000, M = 50000;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
int point = 0, T[N + 5], root, ans[M + 5];
struct node
{
int left, right, ask, id;
}Q[M + 5];
int cmp(node X, node Y)
{
return X.left < Y.left || (X.left == Y.left && X.right < Y.right);
}
struct Node
{
int Val[N + 5], Son[2][N + 5], Level[N + 5], Size[N + 5], Num[N + 5];
inline void up(int u)
{
Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + Num[u];
}
inline void Lturn(int &x)
{
int y = Son[1][x]; Son[1][x] = Son[0][y]; Son[0][y] = x;
up(x), up(y); x = y;
}
inline void Rturn(int &x)
{
int y = Son[0][x]; Son[0][x] = Son[1][y]; Son[1][y] = x;
up(x), up(y); x = y;
}
inline void Newnode(int &u, int v)
{
u = ++point;
Level[u] = rand(), Val[u] = v;
Num[u] = Size[u] = 1, Son[0][u] = Son[1][u] = 0;
} void Insert(int &u, int t)
{
if (!u)
{
Newnode(u, t);
return;
}
Size[u]++;
if (t == Val[u]) Num[u]++;
else if (t < Val[u])
{
Insert(Son[0][u], t);
if (Level[Son[0][u]] < Level[u]) Rturn(u);
}
else
{
Insert(Son[1][u], t);
if (Level[Son[1][u]] < Level[u]) Lturn(u);
}
}
void Delete(int &u, int t)
{
if (!u) return;
if (Val[u] == t)
{
if (Num[u] > 1)
{
Size[u]--, Num[u]--;
return;
}
if (Son[0][u] * Son[1][u] == 0) u = Son[0][u] + Son[1][u];
else if (Level[Son[0][u]] < Level[Son[1][u]]) Rturn(u), Delete(u, t);
else Lturn(u), Delete(u, t);
}
else if (t < Val[u]) Size[u]--, Delete(Son[0][u], t);
else Size[u]--, Delete(Son[1][u], t);
} int Find_num(int u, int t)
{
if (!u) return 0;
if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
else if (t <= Size[Son[0][u]] + Num[u]) return u;
else return Find_num(Son[1][u], t - Size[Son[0][u]] - Num[u]);
}
}Treap;
int sqz()
{
int n = read(), m = read();
rep(i, 1, n) T[i] = read();
rep(i, 1, m) Q[i].left = read(), Q[i].right = read(), Q[i].ask = read(), Q[i].id = i;
sort(Q + 1, Q + m + 1, cmp);
rep(i, Q[1].left, Q[1].right) Treap.Insert(root, T[i]);
ans[Q[1].id] = Treap.Val[Treap.Find_num(root, Q[1].ask)];
rep(i, 2, m)
{
if (Q[i].left <= Q[i - 1].right)
{
rep(j, Q[i - 1].left, Q[i].left - 1) Treap.Delete(root, T[j]);
rep(j, Q[i - 1].right + 1, Q[i].right) Treap.Insert(root, T[j]);
}
else
{
rep(j, Q[i - 1].left, Q[i - 1].right) Treap.Delete(root, T[j]);
rep(j, Q[i].left, Q[i].right) Treap.Insert(root, T[j]);
}
ans[Q[i].id] = Treap.Val[Treap.Find_num(root, Q[i].ask)];
}
rep(i, 1, m) printf("%d\n", ans[i]);
return 0;
}

[POJ2761]Feed the dogs的更多相关文章

  1. 【莫队算法】【权值分块】poj2104 K-th Number / poj2761 Feed the dogs

    先用莫队算法保证在询问之间转移的复杂度,每次转移都需要进行O(sqrt(m))次插入和删除,权值分块的插入/删除是O(1)的. 然后询问的时候用权值分块查询区间k小值,每次是O(sqrt(n))的. ...

  2. [POJ2761] Feed the dogs (Treap)

    题目链接:http://poj.org/problem?id=2761 题目大意:给你n个数,m次查询,m次查询分别是a,b,k,查询下表从a到b的第k小元素是哪个.这m个区间不会互相包含. Trea ...

  3. [Poj2761]Feed the dogs(主席树)

    Desciption 题意:求区间第K小(N<=100000) Solution 主席树模板题 Code #include <cstdio> #include <algorit ...

  4. 【POJ2761】【区间第k大】Feed the dogs(吐槽)

    Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...

  5. poj 2761 Feed the dogs (treap树)

    /************************************************************* 题目: Feed the dogs(poj 2761) 链接: http: ...

  6. 划分树---Feed the dogs

    POJ  2761 Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to fee ...

  7. poj2761 feed the dog

    题目链接:http://poj.org/problem?id=2761 Description Wind loves pretty dogs very much, and she has n pet ...

  8. POJ 2761 Feed the dogs(平衡树or划分树or主席树)

    Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...

  9. POJ 2761 Feed the dogs (主席树)(K-th 值)

                                                                Feed the dogs Time Limit: 6000MS   Memor ...

随机推荐

  1. java web 方面

    1.Tomcat的优化经验. 2.http请求的GET与POST方式的区别. (1)get是从服务器上获取数据,post是向服务器传送数据. (2)get是把参数数据队列加到提交表单的ACTION属性 ...

  2. HeadFirst Ruby 第十五章总结 Saving and loading data

    前言 在上一章讲述了如何进行基础的操作,比如 处理 GET 请求的 get route, 再比如下载 gem 等等方面的知识.在这一章节,作者告诉我们如何储存.处理数据.整个过程分三步走: 首先,当 ...

  3. HTML第一章总结

    第一章总结 HTML那些事儿:Web Sever, Web Browser,HTML files 如果你要做网页,那你写了HTML文档就要上传到 Web Server 上 在客户使用 Web Brow ...

  4. SSH免密钥登陆

    local ipaddress:10.47.39.7:remote ipaddress:10.47.39.8 1.生成公钥和私钥 [root@local ~]# ssh-keygen -t rsa  ...

  5. WAV和PCM文件转换的程序

    using System;using System.IO;using System.Text;using System.Windows.Forms;using System.Runtime.Inter ...

  6. sgu 203 Hyperhuffman

    题意:给出字符出现的次数,问替换成哈夫曼编码后的文本长度. 实际上观察发现就等于树的所有节点的和.用nlogn超时.用O(n),用两个队列,一个放原始数组,一个放新生成的节点. #include &l ...

  7. windows系统文件和linux系统文件

    windows系统文件和linux系统文件 1.单用户操作系统和多用户操作系统 单用户操作系统:指一台计算机在同一时间 只能由一个用户 使用,一个用户独自享用系统的全部硬件和软件资源 Windows ...

  8. 如何设置Git SSH密钥

    1. SSH 存储在user/用户名/.ssh文件夹下 生成SSH密钥 $ ssh-keygen -t rsa -C "your_email" 2. 查看生成的公钥 $ cat ~ ...

  9. 在word中粘贴的图片为什么显示不完整

    一.背景 整理系统测试说明文档,截得图片粘贴到word中显示不完整. 二.错误问题 问题:在word中粘贴的图片为什么显示不完整,如图所示: 三.分析问题: 原因是原来设置的行间距是固定值,图片也作一 ...

  10. 廖雪峰网站:学习python基础知识(一)

    1. python能做什么? 可以做日常任务,比如自动备份你的MP3:可以做网站,很多著名的网站包括YouTube就是Python写的:可以做网络游戏的后台,很多在线游戏的后台都是Python开发的. ...