A Simple Problem with Integers

这个题目首先要打表找规律,这个对2018取模最后都会进入一个循环节,这个循环节的打表要用到龟兔赛跑。

龟兔赛跑算法 floyed判环算法

这个算法我觉得还是很有意思的,可以学习一下。

不过这个题目这个算法打表还是有点难写的。

由这个算法可以得到这个循环节的最大长度是6 最大入环距离是4.

为什么有些循环节不是6,还是可以用6呢,因为每个元素平方最大周期为6,且6是其他所有周期的公倍数。

然后学完之后还是不太会这个题目怎么写,2018 ACM-ICPC 上海大都会 H A Simple Problem with Integers(level 4)(线段树+floyd判环+暴力)

研究了一下这个人的代码,才稍微会了一点点。

这个题目首先是要判断有没有进入负环,如果一个区间的所有叶子节点都已经进入循环节,tim数组

那么这个以后就可以用延迟标记直接记录这个已经推到了这个数的循环节的第几个,mark数组

推到了循环节的第几个可以用pos数组记录,pos数组

然后就是建树,用一个二维的数组来记录,第二维是pos,代表这个数要返回的循环节的位置。

知道这些就可以自己敲代码了。

敲代码的时候越发感觉这个代码写的巧妙之处了,首先它预处理了0~2017 这样之后就可以不用求一个数的平方了,直接迭代。

然后就是这个pos数组,如果来不及push_up 就要求输出结果,这个就已经记录了,然后可以通过这个pos数组来push_up

然后就是这个树的第二维,第二维记录了从这个往后推的6个数,而且每次push_up一次就会把第二维的第一个位置更新为我们所要的结果。

这个题目很好,代码也很巧妙,值得学习。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 5e4 + ;
const int mod = ;
ll mp[maxn], a[maxn];
ll tree[maxn * ][];
int tim[maxn * ], pos[maxn * ], lazy[maxn * ]; void push_up(int id)
{
for (int i = ; i < ; i++)//这个for循环保证i==0的位置就是答案,并且推出了后面的五个位置的数
//这个的主要目的是因为只有在叶子节点的pos才会有值,只要不是叶子节点就都初始化为0,所以我们要保证tree[id][0]的位置就是答案
tree[id][i] = tree[id << ][(pos[id << ] + i) % ] + tree[id << | ][(pos[id<<|] + i) % ];
tim[id] = min(tim[id << ], tim[id << | ]);
pos[id] = ;//为什么这个地方可以赋值为0呢,因为上面的那层for循环已经保证了i==0 的位置就是答案
// printf("tree[%d][0]=%lld\n", id, tree[id][0]);
} void build(int id,int l,int r)
{
tim[id] = pos[id] = lazy[id] = ;
if(l==r)
{
tree[id][] = a[l];//一开始a[l]就是查询结果
for (int i = ; i < ; i++) tree[id][i] = mp[tree[id][i - ]];//这个就是在找a[l]的平方,a[l]平方的平方...
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
push_up(id);
} void push_down(int id)
{
pos[id << ] = (pos[id << ] + lazy[id]) % ;
pos[id << | ] = (pos[id << | ] + lazy[id]) % ;
lazy[id << ] += lazy[id];
lazy[id << | ] += lazy[id];
lazy[id] = ;
} void update(int id,int l,int r,int x,int y)
{
if (y<l || x>r) return;
if(x<=l&&y>=r&&tim[id]>)
{
lazy[id]++;
pos[id] = (pos[id] + ) % ;//为什么这个地方不求出结果,因为求不出来,这个只可以往下传递lazy 标志,并且记录这个是在循环节的哪一个位置
//然后这个位置的上一个节点被更新,或者说这个pos记录就是一种表示求结果的方式,因为之后输出的就是tree[id][pos[id]]
return;
}
if(l==r)
{
pos[id] = ;//如果还是在暴力的阶段就必须赋值为0,pos 和 lazy 只有在进入循环节之后才会有
lazy[id] = ;
tim[id]++;
tree[id][] = mp[tree[id][]];
for (int i = ; i < ; i++) tree[id][i] = mp[tree[id][i - ]];
return;
}
push_down(id);
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y);
if (y > mid) update(id << | , mid + , r, x, y);
push_up(id);
} ll query(int id,int l,int r,int x,int y)
{
if (x > r || y < l) return ;
// printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
if (x <= l && y >= r) return tree[id][pos[id]];
int mid = (l + r) >> ;
push_down(id);
ll ans = ;
if (x <= mid) ans = query(id << , l, mid, x, y);
if (y > mid) ans += query(id << | , mid + , r, x, y);
return ans;
} int main()
{
for (int i = ; i < ; i++) mp[i] = i * i%mod;
int t;
scanf("%d", &t);
for(int cas=;cas<=t;cas++)
{
int n, m;
scanf("%d", &n);
for (int i = ; i <= n; i++) scanf("%lld", &a[i]);
build(, , n);
scanf("%d", &m);
printf("Case #%d:\n",cas);
while (m--) {
char s[];
int l, r;
scanf("%s%d%d", s, &l, &r);
if (l > r) swap(l, r);
if (s[] == 'Q') {
ll ans = query(, , n, l, r);
printf("%lld\n", ans);
}
else update(, , n, l, r);
}
}
return ;
}

A Simple Problem with Integers 循环节 修改 平方 找规律 线段树的更多相关文章

  1. poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)

    题目链接:http://poj.org/problem?id=3468 题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍.线段树用lazy标记差不 ...

  2. POJ-3468-A Simple Problem with Integers(区间更新,求和)-splay或线段树

    区间更新求和 主要用来练习splay树区间更新问题 //splay树的题解 // File Name: 3468-splay.cpp // Author: Zlbing // Created Time ...

  3. HDU 2522 A simple problem( 分数循环节 )

    链接:Here! 思路:模拟除法,当余数再次出现的时候一定是遇到了循环节( 可看下图例子 ),否则的话继续除法的步骤,直到被除数为 0 . 注意:这道题不需要重新申请一个数组来单独存放答案,如果符合要 ...

  4. poj3468 A Simple Problem with Integers(zkw区间修改模板)

    此题是一道线段树的裸题,这里只是为了保存我的zkw线段树模板 #include <cstdio> #include <cstring> #include <iostrea ...

  5. 线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和

    poj3468 A Simple Problem with Integers 题意:O(-1) 思路:O(-1) 线段树功能:update:成段增减 query:区间求和 Sample Input 1 ...

  6. poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   ...

  7. A Simple Problem with Integers 多树状数组分割,区间修改,单点求职。 hdu 4267

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  8. A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 69589   ...

  9. poj 3468 A Simple Problem with Integers【线段树区间修改】

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 79137   ...

随机推荐

  1. python 集合(set)和字典(dictionary)的用法解析

    Table of Contents generated with DocToc ditctaionary and set hash 介绍 集合-set 创建 操作和访问集合的元素 子集.超集.相对判断 ...

  2. defer使用小结

    defer 前言 defer的定义 defer执行的规则 为什么需要defer defer进阶 作为匿名函数 作为函数参数 defer命令执行的时机 defer配合recover 总结 参考 defe ...

  3. <context:component-scan base-package=""> 与 <context:annotation-config 区别

    <context:component-scan base-package=""> <context:annotation-config (2012-11-16 2 ...

  4. C语言小练习之学生信息管理系统

    C语言小练习之学生信息管理系统 main.c文件   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  5. 面试 HTTP ,99% 的面试官都爱问这些问题

    HTTP 和 HTTPS 的区别 HTTP 是一种 超文本传输协议(Hypertext Transfer Protocol),HTTP 是一个在计算机世界里专门在两点之间传输文字.图片.音频.视频等超 ...

  6. Python-气象-大气科学-可视化绘图系列(一)——利用xarray读取netCDF文件并画图(代码+示例)

    本文原创链接:https:////www.cnblogs.com/zhanling/p/12192978.html 1 import numpy as np import xarray as xr i ...

  7. 性能测试-pidstat 问题定位分析

    pidstat 概述 pidstat是sysstat工具的一个命令,用于监控全部或指定进程的cpu.内存.线程.设备IO等系统资源的占用情况.pidstat首次运行时显示自系统启动开始的各项统计信息, ...

  8. 你自学半年也搞不懂的go底层,看这篇。这篇讲 go的数组、切片、Maps

    目录 数组 1.定义数组 2.使用数组 3.定义并赋值 4.数组的大小是类型的一部分 5.数组是值类型(当参数传递到函数中,修改不会改变原来的值) 6.数组长度 7.循环数组 8.多维数组 切片 1. ...

  9. 【题解】POJ3041 Asteroids - 图论 - 二分图匹配

    声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 POJ3041 Asteroids 题目描述 假如你现在正处在一个 \(N*N\ ...

  10. 算法笔记刷题3(codeup 5901)

    今天刷题的速度依旧很慢(小乌龟挥爪.jpg) 我觉得codeup5901中回文串的处理很妙,如果是我自己写的话可能会把数组直接倒过来和原来对比.按照对称规律进行比对的话,工作量可以减少一半. #inc ...