noip2016十连测round2

A: Divisors

题意:给定 m 个不同的正整数 a 1 ,a 2 ,...,a m ,请对 0 到 m 每一个 k 计算,在区间 [1,n] 里有多少正整数

是 a 中恰好 k 个数的约数。 n,ai<=10^9,m<=200

做法:每个数的约数个数为sqrt(n)级别的,所以一共有msqrt(ai)个,对于计算答案,用哈希表判重计算即可。

B:Market

题意:在比特镇一共有 n 家商店,编号依次为 1 到 n。每家商店只会卖一种物品,其中第 i 家商店的物品

单价为 c i ,价值为 v i ,且该商店开张的时间为 t i 。
Byteasar 计划进行 m 次购物,其中第 i 次购物的时间为 T i ,预算为 M i 。每次购物的时候,Byteasar
会在每家商店购买最多一件物品,当然他也可以选择什么都不买。如果购物的时间早于商店开张的时间,
那么显然他无法在这家商店进行购物。
现在 Byteasar 想知道,对于每个计划,他最多能购入总价值多少的物品。请写一个程序,帮助
Byteasar 合理安排购物计划。  n<=300,vi<=300,ci<=10^9;
注意:每次所花金额不得超过预算,预算也不一定要花完,同时预算不能留给其它计划使用。

做法:将物品按时间从小到大排序,询问也按时间排序,然后我们发现单价很大,而价值很小,所以我们设f[i]表示装下价值为i的物品时最小的价钱,那么对于每个询问,就是找到一个最大的i,使得f[i]<=mi,这样不具有二分性,所以我们维护f的后缀和g,这样g数组具有了可二分性,二分即可。

C:Dash Speed

题意:比特山是比特镇的飙车圣地。在比特山上一共有 n 个广场,编号依次为 1 到 n,这些广场之间通过

n − 1 条双向车道直接或间接地连接在一起,形成了一棵树的结构。
因为每条车道的修建时间以及建筑材料都不尽相同,所以可以用两个数字 l i ,r i 量化地表示一条车道
的承受区间,只有当汽车以不小于 l i 且不大于 r i 的速度经过这条车道时,才不会对路面造成伤害。
Byteasar 最近新买了一辆跑车,他想在比特山飙一次车。Byteasar 计划选择两个不同的点 S,T,然
后在它们树上的最短路径上行驶,且不对上面任意一条车道造成伤害。
Byteasar 不喜欢改变速度,所以他会告诉你他的车速。为了挑选出最合适的车速x,Byteasar 一共会
向你询问 m 次。请帮助他找到一条合法的道路,使得路径上经过的车道数尽可能多。

n<=70000,m<=70000;

测试点编号 n m 约定
1 = 5 = 5 无
2 = 20 = 20 无
3 = 50000 = 50000 l i = 1,且 u i = i,v i = i + 1
4 = 70000 = 70000 l i = 1,且 u i = i,v i = i + 1
5 = 50000 = 50000 u i = i,v i = i + 1
6 = 70000 = 70000 u i = i,v i = i + 1
7 = 50000 = 50000 l i = 1
8 = 70000 = 70000 l i = 1
9 = 50000 = 50000 无
10 = 70000 = 70000 无

做法:对于题目中的一条链,我们把每个每条边拆成两个事件,一个是在时间li处把ui染黑,在时间ri+1处把ui染白,然后每个询问就是在时间x处询问最大全黑子段,我们把所有事件按时间排序,然后线段树维护即可,只需记录最大全黑子段,左端最大,右端最大,就可以进行线段树合并了。

对于题目中li=1的情况且是一棵树的情况,我们把边按ri从大到小排序,询问也从大到小排序,这样就只有加边,询问森林的最长链,每个连通块维护最长链,合并的时候的最长链一定来自于那4个点,分6种情况讨论即可,用并查集维护。

对于满分做法;如果学习前面那种做法,把每条边拆成两个事件,这样就相当于求支持加边和删边的动态树的最长链或者是并查集的删边,但是由于顺序不固定所以不支持,没事,我们沿分治的思想,在以速度为区间的线段树上,我们用每条边去覆盖线段树上logn个区间,那么每个询问就是把它到线段树的根节点的路径上所有的边存在时的最长链,所以我们dfs这棵线段树,到一个节点就加边,并查集维护,到了叶子节点就询问,然后回溯的时候撤销操作,由于每次撤销都是最近的一次操作,这样并查集是资瓷的,然后就通过分治把问题转化成了只有加边,成功地解决了这个问题。

时间: 2025-01-02 14:43:30

noip2016十连测round2的相关文章

noip2016十连测题解

以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <bitset> #include <vector> #include <

noip2016十连测 Round #3

A:平均数 题目描述:有一天,小A得到了一个长度为n的序列.他把这个序列的所有连续子序列都列了出来,并对每一个子序列都求了其平均值,然后他把这些平均值写在纸上,并对它们进行排序,最后他报出了第k小的平均值.你要做的就是模仿他的过程. 思路:二分答案,然后判断二分的结果是不是恰好为第k位.首先统计出每一个元素和平均值的差值,记为d[i],对于区间[l,r], 如果d[l]~d[r]之和要大于0,那么这段区间的平均值就一定要大于二分的答案.于是考虑求出前缀和,记为sumd[i],那么 区间[l,r]

NOIp2016 十连测 round1

Claris大爷出的一套模拟题.问别人要到了一份题,加深了自己NOIp要滚粗的感觉. Matser zzDP题,我只能说我第一遍写的时候还写崩了QAQ. //master //by Cydiater //2016.10.21 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <algor

Noi2016十连测第二场-黑暗 (二项式定理/斯特林数+CDQ+NTT)

Noi2016十连测第二场-黑暗 (二项式定理/斯特林数+CDQ+NTT) 题意: n 个点的无向图,每条边都可能存在,一个图的权值是连通块个数的 m 次方,求所有可能的图的权值和. 考虑\(dp[i][j]\)表示\(j\)个点,权值为\(i\)次方 我们首先要预处理出\(n\)个点无向联通图的数量\(g[i]\),模板题:BZOJ-3456 题解 对于\(dp[i][j]\),枚举\(1\)号点所在的连通块大小为\(x\),那么可以得到的是\(dp[i][j]=\sum dp[k][j-x]

暑假第十二测

题解:第一题: 打表找规律,从12以后每次加49,我一直在前十找规律,,找了半天,以后还是多打点,学聪明点 #include <bits/stdc++.h> #define ll long long using namespace std; int zl[4] = {1,5,10,50}; ll ans[] = {0,4,10,20,35,56,83,116,155,198,244,292,341,390,439,488,537,586,635,684,733,782,831,880,929,

NOI十连测 第五测 T1

1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 int f[257][257],n,type,V[257],g[257][257],ans,cnt; 7 char op[204]; 8 int read(){ 9 int t=0,f=1;char ch=getchar(); 10 while

[Noi2016十连测第三场]线段树

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define maxn 100005 8 #define maxk 4000005 9 int n,m,q,tot,t1,t2,ans,L[maxn][18],R[maxn][18]; 1

[NOI十连测] 二进制的世界

题意 给定一个长度为 n 的序列 A , 以及一种位运算 Op . 对于每个位置 x , 求 $\min_{y < x} A[y] ~ Op ~ A[x]$ . n <= 100000, 0 <= A[i] <= 65536 . 一个高效的Trick 我们可以贪心地尽可能使高的位大. g[x] 表示前 8 位为 x 的一个 vector . 我们维护 g 进行剪枝. 1 #include <cstdio> 2 #include <cstring> 3 #in

[BZOJ]2017省队十连测推广赛1

听学长说有比赛就随便打一打. A.普通计算姬 题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值:2.给出l,r,询问以点l为根的子树和.点l+1为根的子树和.点l+2为根的子树和--点r为根的子树和的总和.(点数.操作数不超过10^5) 思路:感觉是三题中最难的.给出的[l,r]区间在树上没有实际意义,不好利用数据结构维护.考虑若不修改,可以一遍dfs算出每个点对应的dfs序,这样每棵子树都对应一个dfs序的区间,前缀和一下就能O(1)查子树和,再按点的编号顺序把子树和前缀和一下