题目链接

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. Date 工具类(包含常用的一些时间方法)

    package com.fh.util; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseE ...

  2. 如何用istio实现应用的灰度发布

    Istio为用户提供基于微服务的流量治理能力.Istio允许用户按照标准制定一套流量分发规则,并且无侵入的下发到实例中,平滑稳定的实现灰度发布功能. 基于华为云的Istio服务网格技术,使得灰度发布全 ...

  3. Selenium自动化测试第一天(下)

    如有任何学习问题,可以添加作者微信:lockingfree 目录 Selenium自动化测试基础 Selenium自动化测试第一天(上) Selenium自动化测试第一天(下) Selenium自动化 ...

  4. linux学习总结----shell编程

    ## 环境变量 ## 全局变量 ``` 常见的全局环境变量 PATH 指令的搜索路径 HOME 用户的家目录 LOGNAME 登录名 SHELL 脚本的类型 使用全局环境变量 echo $PATH 自 ...

  5. stm32之SPI通信协议

    SPI (Serial Peripheral interface),顾名思义就是串行外围设备接口.SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为P ...

  6. 【转】使用CNPM搭建私有NPM

    最近的Node项目中因为数据模型等问题,需要有一个对各个模块进行统一的管理,如果把私有的模型publish到公共的npm不太合适,所以决定使用cnpm搭建一个私有的npm,同时也可以对项目常用的npm ...

  7. 你代码写得这么丑,一定是因为你长得不好看----panboo第一篇博客

    一.个人介绍 我叫潘博,软嵌162,学号1613072055. 以“panboo”名称混迹于各大开源IT论坛与博客. 除了编程,我的最大爱好是篮球与健身,热衷于各种IT技术与运动. 我做过的软件项目有 ...

  8. lintcode-170-旋转链表

    170-旋转链表 给定一个链表,旋转链表,使得每个节点向右移动k个位置,其中k是一个非负数 样例 给出链表1->2->3->4->5->null和k=2 返回4-> ...

  9. java 文件操作知识点

    1.每个文件以一个文件路径和文件名称进行表示,在不同的操作系统环境下,文件路径的表示形式是不一样的,例如在Windows操作系统中一般的表示形式为C:\windows\system,而Unix上的表示 ...

  10. InnoDB,select为啥会阻塞insert?

    MySQL的InnoDB的细粒度行锁,是它最吸引人的特性之一. 但是,如<InnoDB,5项最佳实践>所述,如果查询没有命中索引,也将退化为表锁. InnoDB的细粒度锁,是实现在索引记录 ...