Periodic RMQ Problem

动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值。

感觉有点难写。。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); int Log[N];
int MIN = inf;
struct ST {
int dp[N][], ty;
void build(int n, int b[], int _ty) {
ty = _ty;
for(int i = -(Log[]=-); i < N; i++)
Log[i] = Log[i - ] + ((i & (i - )) == );
for(int i = ; i <= n; i++) dp[i][] = ty * b[i];
for(int j = ; j <= Log[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
int query(int x, int y) {
int k = Log[y - x + ];
return ty * max(dp[x][k], dp[y - ( << k) + ][k]);
}
} rmq; int n, k, q, a[N]; #define lson l, mid, a[x].ls
#define rson mid + 1, r, a[x].rs
namespace SGT1 {
int tot, Rt;
struct Node {
Node() {
mn = inf;
ls = rs = ;
lazy = inf;
}
int mn, ls, rs, lazy;
} a[N * ];
inline void pull(int x) {
a[x].mn = min(a[a[x].ls].mn, a[a[x].rs].mn);
}
inline void push(int x) {
if(a[x].lazy < inf) {
if(!a[x].ls) a[x].ls = ++tot;
if(!a[x].rs) a[x].rs = ++tot;
int lazy = a[x].lazy, l = a[x].ls, r = a[x].rs;
a[l].mn = lazy;
a[r].mn = lazy;
a[l].lazy = lazy;
a[r].lazy = lazy;
a[x].lazy = inf;
}
}
void update(int L, int R, int val, int l, int r, int& x) {
if(!x) x = ++tot;
if(l >= L && r <= R) {
a[x].mn = val;
a[x].lazy = val;
return;
}
push(x);
int mid = l + r >> ;
if(L <= mid) update(L, R, val, lson);
if(R > mid) update(L, R, val, rson);
pull(x);
}
int query(int L, int R, int l, int r, int x) {
if(l >= L && r <= R) return a[x].mn;
push(x);
int mid = l + r >> ;
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return min(query(L, R, lson), query(L, R, rson));
}
} namespace SGT2 {
int tot, Rt;
struct Node {
Node() {
ls = rs = ;
mn = inf;
vis = false;
}
int mn, ls, rs;
bool vis;
} a[N * ];
void update(int L, int R, int l, int r, int& x) {
if(!x) {
x = ++tot;
if(r - l + >= n) a[x].mn = MIN;
else {
int be = (l - ) % n + ;
int ed = be + (r - l);
a[x].mn = rmq.query(be, ed);
}
}
if(a[x].vis) return;
if(l >= L && r <= R) {
a[x].mn = inf;
a[x].vis = true;
return;
}
int mid = l + r >> ;
if(R <= mid) {
update(L, R, lson);
if(!a[x].rs) {
a[x].rs = ++tot;
if(r - mid >= n) {
a[a[x].rs].mn = MIN;
} else {
int be = (mid) % n + ;
int ed = be + (r - mid) - ;
a[a[x].rs].mn = rmq.query(be, ed);
}
}
} else if(L > mid) {
update(L, R, rson);
if(!a[x].ls) {
a[x].ls = ++tot;
if(mid - l + >= n) {
a[a[x].ls].mn = MIN;
} else {
int be = (l - ) % n + ;
int ed = be + (mid - l);
a[a[x].ls].mn = rmq.query(be, ed);
}
}
} else {
update(L, R, lson);
update(L, R, rson);
}
a[x].mn = min(a[a[x].ls].mn, a[a[x].rs].mn);
}
int query(int L, int R, int l, int r, int& x) {
if(!x) {
x = ++tot;
if(r - l + >= n) a[x].mn = MIN;
else {
int be = (l - ) % n + ;
int ed = be + (r - l);
a[x].mn = rmq.query(be, ed);
}
}
if(a[x].vis) return inf;
if(l >= L && r <= R) return a[x].mn;
int mid = l + r >> ;
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return min(query(L, R, lson), query(L, R, rson));
}
} int main() {
scanf("%d%d", &n, &k);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
MIN = min(MIN, a[i]);
}
rmq.build( * n, a, -);
scanf("%d", &q);
while(q--) {
int op; scanf("%d", &op);
if(op == ) {
int L, R, x;
scanf("%d%d%d", &L, &R, &x);
SGT1::update(L, R, x, , n * k, SGT1::Rt);
SGT2::update(L, R, , n * k, SGT2::Rt);
} else {
int L, R;
scanf("%d%d", &L, &R);
printf("%d\n", min(SGT1::query(L, R, , n * k, SGT1::Rt), SGT2::query(L, R, , n * k, SGT2::Rt)));
}
}
return ;
} /*
*/

简化

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); int Log[N];
int MIN = inf;
struct ST {
int dp[N][], ty;
void build(int n, int b[], int _ty) {
ty = _ty;
for(int i = -(Log[]=-); i < N; i++)
Log[i] = Log[i - ] + ((i & (i - )) == );
for(int i = ; i <= n; i++) dp[i][] = ty * b[i];
for(int j = ; j <= Log[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
int query(int x, int y) {
int k = Log[y - x + ];
return ty * max(dp[x][k], dp[y - ( << k) + ][k]);
}
} rmq; int n, k, q, a[N]; inline int getVal(int l, int r) {
if(r - l + >= n) return MIN;
int be = (l - ) % n + ;
int ed = be + (r - l);
return rmq.query(be, ed);
} #define lson l, mid, a[x].ls
#define rson mid + 1, r, a[x].rs
namespace SGT {
int tot, Rt;
struct Node {
Node() {
mn = inf;
ls = rs = ;
lazy = inf;
}
int mn, ls, rs, lazy;
} a[N * ];
inline void pull(int x) {
a[x].mn = min(a[a[x].ls].mn, a[a[x].rs].mn);
}
inline void push(int x, int l, int r) {
int mid = l + r >> ;
if(!a[x].ls) {
a[x].ls = ++tot;
a[a[x].ls].mn = getVal(l, mid);
}
if(!a[x].rs) {
a[x].rs = ++tot;
a[a[x].rs].mn = getVal(mid + , r);
}
if(a[x].lazy < inf) {
int lazy = a[x].lazy, l = a[x].ls, r = a[x].rs;
a[l].mn = lazy;
a[r].mn = lazy;
a[l].lazy = lazy;
a[r].lazy = lazy;
a[x].lazy = inf;
}
}
void update(int L, int R, int val, int l, int r, int& x) {
if(!x) x = ++tot;
if(l >= L && r <= R) {
a[x].mn = val;
a[x].lazy = val;
return;
}
push(x, l, r);
int mid = l + r >> ;
if(L <= mid) update(L, R, val, lson);
if(R > mid) update(L, R, val, rson);
pull(x);
}
int query(int L, int R, int l, int r, int x) {
if(l >= L && r <= R) {
if(!x) return getVal(l, r);
return a[x].mn;
}
push(x, l, r);
int mid = l + r >> ;
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return min(query(L, R, lson), query(L, R, rson));
}
} int main() {
scanf("%d%d", &n, &k);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
MIN = min(MIN, a[i]);
}
rmq.build( * n, a, -);
scanf("%d", &q);
while(q--) {
int op; scanf("%d", &op);
if(op == ) {
int L, R, x;
scanf("%d%d%d", &L, &R, &x);
SGT::update(L, R, x, , n * k, SGT::Rt);
} else {
int L, R;
scanf("%d%d", &L, &R);
printf("%d\n", SGT::query(L, R, , n * k, SGT::Rt));
}
}
return ;
} /*
*/

指针

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 2e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); int Log[N];
int MIN = inf;
struct ST {
int dp[N][], ty;
void build(int n, int b[], int _ty) {
ty = _ty;
for(int i = -(Log[]=-); i < N; i++)
Log[i] = Log[i - ] + ((i & (i - )) == );
for(int i = ; i <= n; i++) dp[i][] = ty * b[i];
for(int j = ; j <= Log[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
int query(int x, int y) {
int k = Log[y - x + ];
return ty * max(dp[x][k], dp[y - ( << k) + ][k]);
}
} rmq; int n, k, q, a[N]; inline int getVal(int l, int r) {
if(r - l + >= n) return MIN;
int be = (l - ) % n + ;
int ed = be + (r - l);
return rmq.query(be, ed);
} struct Node {
Node* ls, *rs;
int mn, lazy;
Node(int l, int r) {
ls = rs = NULL;
mn = getVal(l, r);
lazy = -;
}
}; #define lson l, mid, rt->ls
#define rson mid + 1, r, rt->rs inline void pull(Node* rt) {
rt->mn = min(rt->ls->mn, rt->rs->mn);
}
inline void push(Node* rt, int l, int r) {
int mid = l + r >> ;
if(!rt->ls) rt->ls = new Node(l, mid);
if(!rt->rs) rt->rs = new Node(mid + , r);
if(rt->lazy != -) {
rt->ls->mn = rt->ls->lazy = rt->lazy;
rt->rs->mn = rt->rs->lazy = rt->lazy;
rt->lazy = -;
}
} void update(int L, int R, int val, int l, int r, Node* rt) {
if(R < l || L > r) return;
if(l >= L && r <= R) {
rt->mn = rt->lazy = val;
return;
}
push(rt, l, r);
int mid = l + r >> ;
update(L, R, val, lson);
update(L, R, val, rson);
pull(rt);
} int query(int L, int R, int l, int r, Node* rt) {
if(R < l || L > r) return inf;
if(l >= L && r <= R) {
if(rt) return rt->mn;
else return getVal(l, r);
}
push(rt, l, r);
int mid = l + r >> ;
return min(query(L, R, lson), query(L, R, rson));
} int main() {
scanf("%d%d", &n, &k);
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
MIN = min(MIN, a[i]);
}
rmq.build( * n, a, -);
Node* Rt = new Node(, n * k);
scanf("%d", &q);
while(q--) {
int op; scanf("%d", &op);
if(op == ) {
int L, R, x;
scanf("%d%d%d", &L, &R, &x);
update(L, R, x, , n * k, Rt);
} else {
int L, R;
scanf("%d%d", &L, &R);
printf("%d\n", query(L, R, , n * k, Rt));
}
}
return ;
} /*
*/

Codeforces 803G Periodic RMQ Problem 线段树的更多相关文章

  1. codeforces 803G Periodic RMQ Problem

    codeforces 803G Periodic RMQ Problem 题意 长度为\(1e5\)的数组复制\(1e4\)次,对新的数组进行区间覆盖和区间最小值查询两种操作,操作次数\(1e5\). ...

  2. Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

    思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 els ...

  3. bzoj 3489 A simple rmq problem - 线段树

    Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...

  4. CodeForces 52C Circular RMQ (线段树)

    线段树区间更新维护最小值...记得下放标记... 如果线段树上的一个完整区间被修改,那么最小值和最大值增加相应的值后不变, 会改变是因为一部分改变而另外一部分没有改变所以维护一下就好. 询问的时候也要 ...

  5. (WAWAWAWAWAWAW) G. Periodic RMQ Problem

    没有联通门 : Codeforces G. Periodic RMQ Problem /* Codeforces G. Periodic RMQ Problem MMP 什么动态开点线段树啊 ... ...

  6. AC日记——Periodic RMQ Problem codeforces 803G

    G - Periodic RMQ Problem 思路: 题目给一段序列,然后序列复制很多次: 维护序列很多次后的性质: 线段树动态开点: 来,上代码: #include <cstdio> ...

  7. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  8. CF803G - Periodic RMQ Problem 动态开点线段树 或 离线

    CF 题意 有一个长度为n × k (<=1E9)的数组,有区间修改和区间查询最小值的操作. 思路 由于数组过大,直接做显然不行. 有两种做法,可以用动态开点版本的线段树,或者离线搞(还没搞)( ...

  9. Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...

随机推荐

  1. LA 6893 矩阵HASH (模板)

    #include<stdio.h> #include<string.h> typedef unsigned long long ULL; ; ; int test,n,m,x, ...

  2. Laravel 5.2服务----用户验证Auth相关问题

    关于laravel的auth()用户认证这一块,面前我也是,有用到,有碰到什么问题我就记录下来. 手动认证用户 <?php namespace App\Http\Controllers; use ...

  3. Spring Cloud Sleuth超详细实战

    为什么需要Spring Cloud Sleuth 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去 ...

  4. js实现两种排序算法——冒泡、快速排序

    * 一:冒牌排序1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置要实现上述规则需要用到两层for循环,外层从第一个数到倒数第二个数,内层从 ...

  5. Oracle+PL+SQL从入门到精通.丁士锋.清华大学出版社.2012

    \t第1篇 pl/sql开发入门第1章 oracle 11g数据库系统1.1 关系型数据库系统介绍1.1.1 什么是关系型数据模型1.1.2 数据库系统范式1.1.3 关系型数据库管理系统1.1.4 ...

  6. 快速理解VirtualBox的四种网络连接方式

    VirtualBox中有4中网络连接方式: NAT Bridged Adapter Internal Host-only Adapter VMWare中有三种,其实他跟VMWare 的网络连接方式都是 ...

  7. PHP实现网络Socket及IO多路复用

    一直以来,PHP很少用于socket编程,毕竟是一门脚本语言,效率会成为很大的瓶颈,但是不能说PHP就无法用于socket编程,也不能说PHP的socket编程性能就有多么的低,例如知名的一款PHP ...

  8. 对一个元素 同时添加单击onclick 和 双击ondblclick 触发冲突的解决

    需求说明:单击列表项内容后,吧啦吧啦,双击列表项内容后,巴拉巴拉巴拉~~~ 解决思路:卧槽 ,其实我是没思路的,当时唯一的想法就是,看个人点击鼠标的速度了,双击快一点,触发双击事件ლ(′◉❥◉`ლ), ...

  9. Practical Web Penettation Testing (the first one Mutillidae 大黄蜂 之二)

    1.how  to use dpkg cmmand first it can be used for list all software , dpkg -l  (由于kali linux 没有启动所以 ...

  10. vue中 裁剪,预览,上传图片 的插件

    参考地址: https://github.com/dai-siki/vue-image-crop-upload