题目链接

BZOJ4105

题解

平方操作orz,虽说应该是线段树,但是不会维护啊QAQ

小瞧一眼题解。。。

平方成环?环长\(lcm\)小于\(60\)?

果然还是打表找规律题。。。。

那就很好做了,先预处理每个数是否在环上,如果当前区间存在数不在环上,就暴力修改

如果当前区间都在环上了,就处理出环,之后每次修改只在环上走一步即可

每次修改可能会重置\(logn\)个节点的信息,由于重置一次要求出环,是\(O(60)\)的,所以修改总复杂度是\(O(60nlogn)\)的,可以接受

#include<algorithm>
#include<iostream>
#include<cstdio>
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define ls (u << 1)
#define rs (u << 1 | 1)
#define res register
using namespace std;
const int maxn = 100005,maxm = 10005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int ou[20];
inline void write(int x){
if (!x) {putchar('0'); return;}
int tmp = 0;
while (x) ou[++tmp] = x % 10,x /= 10;
while (tmp) putchar(ou[tmp--] + '0');
}
int n,m,P,A[maxn],Nxt[maxn],inc[maxn];
int sum[maxn << 2],tag[maxn << 2],val[maxn << 2];
int pos[maxn << 2],siz[maxn << 2];
int cir[maxn << 2][65],L,R;
inline int gcd(int a,int b){return b ? gcd(b,a % b) : a;}
inline int lcm(int a,int b){return a / gcd(a,b) * b;}
void upd(int u){
sum[u] = sum[ls] + sum[rs];
val[u] = val[ls] & val[rs];
if (val[u]){
pos[u] = 0;
siz[u] = lcm(siz[ls],siz[rs]);
for (int i = pos[ls],j = pos[rs],k = 0; k < siz[u]; k++){
cir[u][k] = cir[ls][i] + cir[rs][j];
i = i + 1 == siz[ls] ? 0 : i + 1;
j = j + 1 == siz[rs] ? 0 : j + 1;
}
}
}
void pd(int u){
if (tag[u]){
pos[ls] = pos[ls] + tag[u];
pos[rs] = pos[rs] + tag[u];
if (pos[ls] >= siz[ls]) pos[ls] %= siz[ls];
if (pos[rs] >= siz[rs]) pos[rs] %= siz[rs];
sum[ls] = cir[ls][pos[ls]];
sum[rs] = cir[rs][pos[rs]];
tag[ls] += tag[u]; tag[rs] += tag[u];
tag[u] = 0;
}
}
void build(int u,int l,int r){
if (l == r){
sum[u] = A[l];
val[u] = inc[A[l]];
if (val[u]){
pos[u] = 0;
siz[u] = 0;
cir[u][siz[u]++] = A[l];
for (int i = Nxt[A[l]]; i != A[l]; i = Nxt[i])
cir[u][siz[u]++] = i;
}
return;
}
int mid = l + r >> 1;
build(ls,l,mid);
build(rs,mid + 1,r);
upd(u);
}
void modify(int u,int l,int r){
if (l == r){
if (val[u]){
pos[u] = (pos[u] + 1) % siz[u];
sum[u] = cir[u][pos[u]];
}
else {
sum[u] = Nxt[sum[u]];
if (inc[sum[u]]){
val[u] = true;
pos[u] = 0;
siz[u] = 0;
cir[u][siz[u]++] = sum[u];
for (int i = Nxt[sum[u]]; i != sum[u]; i = Nxt[i])
cir[u][siz[u]++] = i;
}
}
return;
}
if (l >= L && r <= R && val[u]){
pos[u] == siz[u] - 1 ? pos[u] = 0 : pos[u]++;
sum[u] = cir[u][pos[u]];
tag[u]++;
return;
}
pd(u);
int mid = l + r >> 1;
if (mid >= L) modify(ls,l,mid);
if (mid < R) modify(rs,mid + 1,r);
upd(u);
}
int query(int u,int l,int r){
if (l >= L && r <= R) return sum[u];
pd(u);
int mid = l + r >> 1;
if (mid >= R) return query(ls,l,mid);
if (mid < L) return query(rs,mid + 1,r);
return query(ls,l,mid) + query(rs,mid + 1,r);
}
int vis[maxn],fa[maxn],now;
void dfs(int u){
vis[u] = now;
if (vis[Nxt[u]]){
if (vis[Nxt[u]] != now) return;
else {
for (int i = u; i != Nxt[u]; i = fa[i])
inc[i] = true;
inc[Nxt[u]] = true;
return;
}
}
fa[Nxt[u]] = u; dfs(Nxt[u]);
}
int main(){
n = read(); m = read(); P = read(); REP(i,n) A[i] = read();
for (int i = 0; i < P; i++) Nxt[i] = i * i % P;
for (int i = 0; i < P; i++)
if (!vis[i]){now++; dfs(i);}
build(1,1,n);
int opt;
while (m--){
opt = read(); L = read(); R = read();
if (!opt) modify(1,1,n);
else write(query(1,1,n)),putchar('\n');
}
return 0;
}

BZOJ4105 [Thu Summer Camp 2015]平方运算 【线段树】的更多相关文章

  1. 2018.10.18 bzoj4105: [Thu Summer Camp 2015]平方运算(线段树)

    传送门 线段树妙题. 显然平方几次就会循环(打表证明不解释). 然后所有环长度的lcmlcmlcm不大于70. 因此维护一下当前区间中的节点是否全部在环上. 不是直接暴力到叶子节点修改. 否则整体打标 ...

  2. bzoj4105: [Thu Summer Camp 2015]平方运算

    填坑 我不知道怎么算的,但是所有环的LCM数不会超过60 然后用线段树维护这个东西,每个节点记录子树内的循环节 没到循环节的暴力枚举 复杂度是nlogn再乘以循环节长度 #include<cst ...

  3. bzoj:4105: [Thu Summer Camp 2015]平方运算

    Description   Input 第一行有三个整数N,M,p,分别代表序列的长度.平方操作与询问操作的总次数以及在平方操作中所要模的数.   接下来一行N个数代表一开始的序列{X1,X2,... ...

  4. 4105: [Thu Summer Camp 2015]平方运算

    首先嘛这道题目只要知道一个东西就很容易了:所有循环的最小公约数<=60,成一条链的长度最大为11,那么我们就可以用一个很裸的方法.对于在链上的数,我们修改直接暴力找出并修改.对于在环上的数,我们 ...

  5. [Thu Summer Camp 2015]解密运算

    4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec  Memory Limit: 512 MB Description 对于一个长度为N的字符串,我 ...

  6. 【BZOJ 4104】 4104: [Thu Summer Camp 2015]解密运算 (智商)

    4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 370  Solved: 237 De ...

  7. BZOJ4104:[Thu Summer Camp 2015]解密运算——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4104 对于一个长度为N的字符串,我们在字符串的末尾添加一个特殊的字符".".之 ...

  8. BZOJ4104 [Thu Summer Camp 2015]解密运算 【乱搞】

    题目链接 BZOJ4104 题解 我们将已知字符排序,由循环就可以得到一个对应关系 如样例就是: 0->第5行 1->第1行 1->第2行 1->第3行 1->第5行 2 ...

  9. bzoj 4104 [Thu Summer Camp 2015]解密运算——思路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4104 想了很久,想出一个 nlogn (也许是 n2logn )的,可惜空间是 n2 . 已 ...

随机推荐

  1. iOS 测试工具reveal可视化调试工具的使用

    简单翻译一下reveal可视化图形工具插入项目的官方文档(官方英文版file:///Applications/Reveal.app/Contents/SharedSupport/Documentati ...

  2. Linux命令应用大词典-第8章 日期和时间

    8.1 cal:显示日历信息 8.2 date:显示和设置系统日期和时间 8.3 hwclock:查看和设置硬件时钟 8.4 clock:查看和设置硬件时钟 8.5 clockdiff:主机之间测量时 ...

  3. Spring 配置请求过滤器,编码格式设为UTF-8,避免中文乱码

    <!-- 配置请求过滤器,编码格式设为UTF-8,避免中文乱码--> <filter> <filter-name>springUtf8Encoding</fi ...

  4. NMAP-高级用法

    1.报文分段 2.偏移 –mtu后面的数字是8的倍数 3.源端口欺骗 4.指定报文长度 5.ttl 6.mac地址伪造 0代表随机伪造 7.正常输出 8.输出为xml 9.输出为grep 10.输出所 ...

  5. Entity Framework 基本概念

    概念 LINQ to Entities 一种 LINQ 技术,使开发人员可以使用 LINQ 表达式和 LINQ 标准查询运算符,针对实体数据模型 (EDM) 对象上下文创建灵活的强类型化查询. ESQ ...

  6. str和repr

    在Python2.6和Python3.0以及更早的版本中,在交互式模式下的输出本质上是使用repr,因此对于一些浮点数运算,会显示很多位: 4 / 5.0 #0.8000000000000004 但是 ...

  7. MyBatis 基本构成与框架搭建

    核心组件 SqlSessionFactoryBuilder (构造器) 根据配置信息(eg:mybatis-config.xml)或者代码来生成SqlSessionFactory. SqlSessio ...

  8. “今日校园” App 用户体验分析

    一.背景 为进一步提升信息化应用水平,更好的服务师生,南通大学智慧校园移动端APP“今日校园”定于11月5日正式上线运行.登陆APP可浏览学校新闻.校园生活.各部门微信公众号等内容,查看校内通知.校内 ...

  9. oracle数据库之PL/SQL 块结构和组成元素

    一.PL/SQL 块 (一)PL/SQL 程序由三个块组成,即声明部分.执行部分.异常处理部分 PL/SQL 块的结构如下: 1.DECLARE /* 声明部分: 在此声明 PL/SQL 用到的变量, ...

  10. Java容器之Set接口

    Set 接口: 1. Set 接口是 Collection 的子接口,Set 接口没有提供额外的方法,但实现 Set 接口的容器类中的元素是没有顺序的,且不可以重复: 2. Set 容器可以与数学中的 ...