题目链接: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. ASP.NET Core 过滤器中使用依赖注入

    如何给过滤器ActionFilterAttribute也用上构造函数注入呢? 一般自定义的过滤器直接用特性方式标识就能使用 [ContentFilter] 因为构造函数在使用的时候要求传参,然后我们可 ...

  2. python3-使用requests模拟登录网易云音乐

    # -*- coding: utf-8 -*- from Crypto.Cipher import AES import base64 import random import codecs impo ...

  3. Java NIO和IO的区别

    下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异. 复制代码 代码如下: IO NIO面向流 面向缓冲阻塞IO 非阻塞IO无 选择器 面向流与面向缓冲 Java NIO ...

  4. 小米cc9和vivo z5 对比

    (一)大致对比 1.小米 cc9(6GB+128GB.  1899元. 白色恋人(白色)) https://item.mi.com/product/10000163.html 2.vivo Z5 (6 ...

  5. flask 扩展包

    1.pipenv install python-dotenv  (管理项目环境变量): 2.pipenv install watchdog --dev(监测文件变动,一般开发时使用): 3.pipen ...

  6. Android笔记(五十八)Android总结:四大组件——Activity篇

    什么是Activity Activity是一种包含用户界面的组件,主要用于和用户进行交互,一个APP通常由多个Activity组成. 每个Activity都对应一个布局文件,通过setContentV ...

  7. 使用Junit测试框架学习Java

    前言 在日常的开发中,离不开单元测试,而且在学习Java时,特别是在测试不同API使用时要不停的写main方法,显得很繁琐,所以这里介绍使用Junit学习Java的方法.此外,我使用log4j将结果输 ...

  8. java计算两个经纬度之间的距离

    /** * 计算点 是否在一个固定点的半径范围内 * @2016年10月20日 * @param a 经度1 已知 * @param b 纬度1 已知 * @param x 经度2 * @param ...

  9. samba简单配置

    Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成.SMB (Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种 ...

  10. 使用Visual Studio快速开发STM32F4-Discovery探索板入门

    本本将主要介绍如何使用Visual Studio创建一个基于STM32F4-Discovery探索板的简单工程. 本文使用以下硬件和软件: ●      Microsoft Visual Studio ...