题目链接:UOJ

这题的时间线段树非常的妙。

对时间建立线段树,修改的时候在后面加,每当填满一个节点之后就合并进它的父亲。

对于一个节点维护序列,发现这是一个分段函数,合并就是归并排序。于是就形成了差不多这样的一个结构。

查询的时候在分段函数上二分。

因为每个断点至多被合并\(\log n\)次,所以时间复杂度是\(O(n\log^2n+m\log n)\)

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = 100003;
int id, tot, n, m, mod, val[N];
struct Node {
int a, b, r;
inline Node(int _a = 0, int _b = 0, int _r = 0): a(_a), b(_b), r(_r){}
inline Node operator * (const Node &o) const {
return Node((LL) a * o.a % mod, ((LL) b * o.a + o.b) % mod, min(r, o.r));
}
inline bool operator < (const Node &o) const {
if(r != o.r) return r < o.r;
if(a != o.a) return a < o.a;
return b < o.b;
}
};
vector<Node> seg[N << 2];
inline void add(int x, int l, int r, int a, int b){
seg[x].push_back(Node(1, 0, l - 1)); seg[x].push_back(Node(a, b, r)); if(r < n) seg[x].push_back(Node(1, 0, n));
}
inline void merge(vector<Node> &res, const vector<Node> A, const vector<Node> B){
int p = 0, q = 0;
while(p < A.size() && q < B.size()){
res.push_back(A[p] * B[q]);
if(A[p].r == B[q].r) ++ p, ++ q;
else if(A[p].r < B[q].r) ++ p;
else ++ q;
}
}
inline void change(int x, int L, int R, int l, int r, int a, int b){
if(L == R){add(x, l, r, a, b); return;}
int mid = L + R >> 1;
if(tot <= mid) change(x << 1, L, mid, l, r, a, b);
else change(x << 1 | 1, mid + 1, R, l, r, a, b);
if(tot == R) merge(seg[x], seg[x << 1], seg[x << 1 | 1]);
}
int ans;
inline void query(int x, int L, int R, int l, int r, int k){
if(l <= L && R <= r){
auto it = lower_bound(seg[x].begin(), seg[x].end(), Node(0, 0, k));
ans = ((LL) ans * (it -> a) + (it -> b)) % mod;
return;
}
int mid = L + R >> 1;
if(l <= mid) query(x << 1, L, mid, l, r, k);
if(mid < r) query(x << 1 | 1, mid + 1, R, l, r, k);
}
int main(){
scanf("%d%d%d", &id, &n, &mod);
for(Rint i = 1;i <= n;i ++)
scanf("%d", val + i);
scanf("%d", &m);
for(Rint i = 1;i <= m;i ++){
int opt, l, r, a, b;
scanf("%d%d%d%d", &opt, &l, &r, &a);
if(id & 1) l ^= ans, r ^= ans;
if(opt == 1){
scanf("%d", &b); ++ tot;
change(1, 1, n, l, r, a, b);
} else if(opt == 2){
if(id & 1) a ^= ans;
ans = val[a];
query(1, 1, n, l, r, a);
printf("%d\n", ans);
}
}
}

UOJ46 【清华集训2014】玄学 【时间线段树】的更多相关文章

  1. UOJ46 清华集训2014玄学(线段树)

    注意到操作有结合律,容易想到用一个矩形表示第i次操作对第j个位置的数的影响.那么修改是单行内的区间修改,而查询是单列内的区间查询.这样二维线段树上以列为外层行为内层直接打标记就可以维护.然后就喜闻乐见 ...

  2. [UOJ46][清华集训2014]玄学

    uoj description 给出\(n\)个变换,第\(i\)个变换是将区间中\(l_i,r_i\)的数\(x\)变成\((a_ix+b_i)\mod m\). 每次会新增一个变换,或者查询询问如 ...

  3. 【uoj#46】 [清华集训2014] 玄学

      题目传送门:uoj46   题意简述:要求在序列上维护一个操作间支持结合律的区间操作,查询连续一段时间内的操作对单点的作用效果,\(n \leq 10^5,m \leq 6 \times 10^5 ...

  4. uoj #46[清华集训2014]玄学

    uoj 因为询问是关于一段连续区间内的操作的,所以对操作构建线段树,这里每个点维护若干个不交的区间,每个区间\((l,r,a,b)\)表示区间\([l,r]\)内的数要变成\(ax+b\) 每次把新操 ...

  5. UOJ #164. 【清华集训2015】V | 线段树

    题目链接 UOJ #164 题解 首先,这道题有三种询问:区间加.区间减(减完对\(0\)取\(\max\)).区间修改. 可以用一种标记来表示--标记\((a, b)\)表示把原来的值加上\(a\) ...

  6. LOJ 164 【清华集训2015】V——线段树维护历史最值

    题目:http://uoj.ac/problem/164 把操作改成形如 ( a,b ) 表示加上 a 之后对 b 取 max 的意思. 每个点维护当前的 a , b ,还有历史最大的 a , b 即 ...

  7. 【题解】【LibreOJ Round #6】花团 LOJ 534 时间线段树分治 背包

    Prelude 题目链接:萌萌哒传送门(/≧▽≦)/ Solution 如果完全离线的话,可以直接用时间线段树分治来做,复杂度\(O(qv \log q)\). 现在在线了怎么办呢? 这其实是个假在线 ...

  8. uoj 41 【清华集训2014】矩阵变换 婚姻稳定问题

    [清华集训2014]矩阵变换 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/41 Description 给出 ...

  9. AC日记——【清华集训2014】奇数国 uoj 38

    #38. [清华集训2014]奇数国 思路: 题目中的number与product不想冲: 即为number与product互素: 所以,求phi(product)即可: 除一个数等同于在模的意义下乘 ...

随机推荐

  1. Crontab详细用法-定时任务详解

    crontab是linux系统或unix系统中常用的定时命令,使用crontab你可以在指定的时间执行一个shell脚本或者一系列Linux/unix命令.例如系统管理员安排一个备份任务使其每天都运行 ...

  2. 使用 SetParent 制作父子窗口的时候,如何设置子窗口的窗口样式以避免抢走父窗口的焦点

    原文:使用 SetParent 制作父子窗口的时候,如何设置子窗口的窗口样式以避免抢走父窗口的焦点 制作传统 Win32 程序以及 Windows Forms 程序的时候,一个用户看起来独立的窗口本就 ...

  3. Oracle 检索数据(查询数据、select语句)

    用户对表或视图最常进行的操作就是检索数据,检索数据可以通过 select 语句来实现,该语句由多个子句组成,通过这些子句完成筛选.投影和连接等各种数据操作,最终得到想要的结果. 语法: select ...

  4. day28-python之property

    1.property用法 # class Goods: # def __init__(self): # # 原价 # self.original_price = 100 # # 折扣 # self.d ...

  5. UCOSIII钩子函数

    OSIdleTaskHook 空闲任务调用这个函数,可以用来让CPU进入低功耗模式 void OSIdleTaskHook (void) { #if OS_CFG_APP_HOOKS_EN > ...

  6. [转]数据库性能优化(老Key)

    数据库性能优化一:数据库自身优化(大数据量) https://www.cnblogs.com/AK2012/archive/2012/12/25/2012-1228.html 数据库性能优化二:数据库 ...

  7. 代替for-in 遍历对象

    object.keys() object.getOwnPropertyName()

  8. 02- web-mini框架添加路由、MySQL(二)

    本篇在上篇的基础上为其增设路由功能,同时将上篇中的数据库中数据备份添加进去. 一.装饰器 在之前有介绍过为一个函数不改变源代码不改变原函数的调用方式下为其增设附加功能,需要用到装饰器,而在该上篇的we ...

  9. Mongodb之增删改查操作

    一.创建一个数据库 在我们使用MongoDB数据库时引进了这样一个知识,“对于mongodb,使用了不存在的对象,就等于在创建这个对象”,所以创建数据库的操作就比较简单 在我们使用mysql数据库时u ...

  10. 【转】CCS5.5从硬盘读入.dat数据格式的单张图像

    首页 博客 学院 CSDN学院                            下载 论坛 APP CSDN                            问答 商城 活动 VIP会员 ...