多校hdu5726 线段树+预处理
第一问是没有修改的线段树,第二问暴力预处理,因为gcd的结果不会很多
在预处理阶段需要把每个区间的gcd相等的数量储存起来(用map容器),在一个序列例如:12467,枚举左区间L直到n此处时间为O(n),l=1时寻找右区间随着r的增大gcd单调不增,在某个区域内gcd相等想到用二分查找时间是O(logn),再加上线段树查找用到时间O(logn),总时间是O(n*logn*longn)会超时,所以需要更优。
解决办法:左区间固定时利用线段树找到gcd减小的区间,从l到gcd减小的区间gcd相等。
#include<map>
#include<stdio.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int N = 4e5 + 10;
int T, n, m, g[N], a[N], l, r, q, cas = 0;
map<int, LL> M;
int gcd(int x, int y) { return x%y ? gcd(y, x%y) : y; }
void build(int x, int l, int r)
{
if (l == r) scanf("%d", &g[x]), a[l] = g[x];
else
{
int mid = l + r >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
g[x] = gcd(g[x << 1], g[x << 1 | 1]);
}
} int get(int x, int l, int r, int ll, int rr)
{
if (ll <= l&&r <= rr) return g[x];
int mid = l + r >> 1;
int x1 = 0, x2 = 0;
if (ll <= mid) x1 = get(x << 1, l, mid, ll, rr);
if (rr > mid) x2 = get(x << 1 | 1, mid + 1, r, ll, rr);
return gcd(min(x1, x2), max(x1, x2));
} bool find(int x, int l, int r, int ll, int rr, int u, int &v)
{
if (ll <= l && r <= rr)
{
if (gcd(v, g[x]) < u)
{
if (l == r)
{
q = l; return true;
}
else
{
int mid = l + r >> 1;
if (find(x<<1, l, mid, ll, rr, u, v)) return true;
if (find(x<<1|1, mid + 1, r, ll, rr, u, v)) return true;
}
}
else { v = gcd(v, g[x]); return false; }
}
else
{
int mid = l + r >> 1;
if (ll <= mid&&find(x<<1, l, mid, ll, rr, u, v)) return true;
if (rr > mid&& find(x<<1|1, mid + 1, r, ll, rr, u, v)) return true;
return false;
}
} int main()
{
scanf("%d", &T);
while (T--)
{
M.clear();
scanf("%d", &n);
build(1, 1, n);
for (int i = 1, j, k; i <= n; i++)
{
int kk = get(1, 1, n, i, n);
for (k = i, j = a[i]; k <= n;)
{
if (kk == j) { M[j] += n - k + 1; break; }
int gg = a[i];
find(1, 1, n, i, n, j, gg);
M[j] += q - k;
k = q; j = gcd(a[q], j);
}
}
scanf("%d", &m);
printf("Case #%d:\n", ++cas);
while (m--)
{
scanf("%d%d", &l, &r);
int x = get(1, 1, n, l, r);
printf("%d %lld\n", x, M[x]);
}
}
return 0;
}
多校hdu5726 线段树+预处理的更多相关文章
- HDU 4960 Handling the past 2014 多校9 线段树
首先确定的基本思想是按时间离散化后来建线段树,对于每个操作插入到相应的时间点上 但是难就难在那个pop操作,我之前对pop操作的处理是找到离他最近的那个点删掉,但是这样对于后面的peak操作,如果时间 ...
- HDU 4893 2014多校三 线段树
给定一个初始都为0的序列,有三种操作,前两种比较正常,一个是对某个位置的数add k,另一个是query区间和.然后比较麻烦的是第三个操作,把某个区间里面的每个值改成离它最近的Fibonacci数,如 ...
- HDU 4902 Nice boat 多校4 线段树
给定n个数 第一个操作和普通,区间覆盖性的,把l-r区间的所有值改成固定的val 第二个操作是重点,输入l r x 把l-r区间的所有大于x的数,变成gcd(a[i],x) a[i]即指满足条件的序列 ...
- HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护
给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...
- BZOJ 3173: [Tjoi2013]最长上升子序列 (线段树+BIT)
先用线段树预处理出每个数最终的位置.然后用BIT维护最长上升子序列就行了. 用线段树O(nlogn)O(nlogn)O(nlogn)预处理就直接倒着做,每次删去对应位置的数.具体看代码 CODE #i ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- hdu(预处理+线段树)
给n个数,m个询问, 问任意区间内与其它数互质的数有多少个 比如3个数1 2 4,询问[1,3] 那么答案是1 千万要记住,这样的题目,如果你不转变下,使劲往线段树想(虽然转变之后,也说要用到线段树, ...
- [Bzoj5358][Lydsy1805月赛]口算训练(预处理+动态开点线段树)
5358: [Lydsy1805月赛]口算训练 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 318 Solved: 105[Submit][Stat ...
- BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]
传送门 GTY's gay friends Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
随机推荐
- Python:简述 线程、进程和协程
Python线程 定义:Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- impor ...
- 看懂Gradle脚本(4)- Groovy语法之运算符重载
继续讨论Task定义 回想一下前一篇文章的样例: task myTask { doLast { println 'hello world!' } } 这段脚本定义了一个名为myTask的任务.而且通过 ...
- 集合 Vector ArrayList 集合一
集合是存储对象的,与对象数组不同,集合可以自动的扩大自己的容量,像StringBuffer一样,存储的对象类型可以不一致,(object数组). 方法: add();remove();get();se ...
- VC编译那些事儿
转载自:http://blog.csdn.net/wowolook/article/details/8077153 最近又被ms的编译选译纠结了一下,运行程序是老是弹出0x14b1 or 71 ...
- hoj 2739 中国邮局问题
/*若原图的基图不连通, 或者存在某个点的入度或出度为 0 则无解. 统计所有点的入度出度之差 Di, 对于 Di > 0 的点, 加边(s, i, Di, 0); 对于 Di < 0 的 ...
- MVC架构模式概述
MVC MVC概述: Model–view–controller (MVC) is a software architectural pattern for implementing user int ...
- hdu 5068(线段树+矩阵乘法)
矩阵乘法来进行所有路径的运算, 线段树来查询修改. 关键还是矩阵乘法的结合律. Harry And Math Teacher Time Limit: 5000/3000 MS (Java/Others ...
- es 中 for in for of
arr=[11,22,33,44,55,66,77,88]for (const i in arr){ console.log(i) if (i===4){ console.log(arr[i]) }} ...
- debug_backtrace final catch
<?php function backtrace_str(){ $str = ''; $w = 0; $backtrace = debug_backtrace(); foreach($backt ...
- JavaScript数据结构与算法-散列练习
散列的实现 // 散列类 - 线性探测法 function HashTable () { this.table = new Array(137); this.values = []; this.sim ...