codeforce 381 div2
---恢复内容开始---
C:
由mex函数性质可知 ,对任意一个区间,都需要从0开始依次填1,2直到填满,那么,所有区间最小mex的最大值取决于最短区间长度k。
构造a数组之需要从0~k-1依次填数,即a[i] = i%k
代码如下:
- 1 #include <cstdio>
- 2 #include <cstring>
- 3 #include <algorithm>
- 4 using namespace std;
- 5
- 6 int n, m;
- 7 int main() {
- 8 scanf("%d%d", &n, &m);
- 9 int len = 10000000;
- 10 for(int i = 0; i < m; i++) {
- 11 int x, y;
- 12 scanf("%d%d\n", &x, &y);
- 13 if(y-x+1 < len) {
- 14 len = y-x+1;
- 15 }
- 16 }
- 17 printf("%d\n", len);
- 18 printf("%d", 0);
- 19 for(int i = 1; i < n; i++) {
- 20 printf(" %d", i%len);
- 21 }
- 22 printf("\n");
- 23 return 0;
- 24 }
D:
思路是预处理出每个结点到根结点的距离dist(x), 然后对每个结点u, 找到一个离根结点最近的祖先v, 且满足 dist(u) - dist(v)<= a[u],
然后将树上区间[v, pa[u]] 的值全部+1, pa[u]为u的直接父亲;
维护树上区间值有两种方法:
方法一 O(nlogn):可以用一个栈来维护当前结点u的全部父亲, 然后用线段树的区间修改来维护区间值, 则结点u的答案为它出栈时在线段树中的值;
方法二 O(n): 对于区间[l, r] ,将区间内容全部加1的简单方法是, 在 l-1 处标记+1, r-1处标记-1,则val[i] += val[i+1]
对于树上区间[v, u], 只需将sum[pa[v]]--, sum[pa[u]]++, 计算sum[i] = Σ x € {sum[j] | j 是 i 的儿子}
代码如下:
- 1 #include <cstdio>
- 2 #include <cstring>
- 3 #include <algorithm>
- 4 #include <vector>
- 5
- 6 using namespace std;
- 7 typedef long long LL;
- 8
- 9 const int maxn = 2e5 + 10;
- 10 vector<int> G[maxn];
- 11 vector<int> S;
- 12 int a[maxn];
- 13 LL d[maxn]; //节点到1的距离
- 14 int w[maxn]; //节点到父亲的距离
- 15 int ans[maxn];
- 16 int n;
- 17 int p[maxn];
- 18 void cal_d(int u, LL dist) {
- 19 d[u] = dist;
- 20 for(int i = 0; i < G[u].size(); i++) {
- 21 int v = G[u][i];
- 22 cal_d(v, dist+w[v]);
- 23 }
- 24 }
- 25 int b_search(int cur, LL val, int L, int R) {
- 26 while(L < R) {
- 27 int M = L + (R-L)/2;
- 28 if(d[cur]-d[S[M]] <= val) R = M;
- 29 else L = M+1;
- 30 }
- 31 return L;
- 32 }
- 33 void dfs_upd(int u) {
- 34 if(!S.empty()) {
- 35 int k = b_search(u, a[u], 0, S.size());
- 36 if(k < S.size()) {
- 37 int v = S[k];
- 38 ans[p[v]]--;
- 39 ans[p[u]]++;
- 40 }
- 41 }
- 42 S.push_back(u);
- 43 for(int i = 0; i < G[u].size(); i++)
- 44 dfs_upd(G[u][i]);
- 45 S.pop_back();
- 46 }
- 47
- 48 void dfs_ans(int u) {
- 49 int &t = ans[u];
- 50 for(int i = 0; i < G[u].size(); i++) {
- 51 int v = G[u][i];
- 52 dfs_ans(v);
- 53 t += ans[v];
- 54 }
- 55 }
- 56
- 57 int main() {
- 58 scanf("%d", &n);
- 59 for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
- 60 for(int i = 2; i <= n; i++) {
- 61 scanf("%d%d", &p[i], &w[i]);
- 62 G[p[i]].push_back(i);
- 63 }
- 64 cal_d(1, 0);
- 65 dfs_upd(1);
- 66 dfs_ans(1);
- 67 printf("%d", ans[1]);
- 68 for(int i = 2; i <= n; i++) printf(" %d", ans[i]);
- 69 printf("\n");
- 70 }
E:
Let's consider the difference between two adjacent elements of array: a[i] = arr[i + 1] - arr[i]. Let us add d in the segment from l to r. Then it is clear that in the array a will change no more than two values (at the ends of the addition of the segment), because if l < i < r, then a[i] = arr[i + 1] + d - (arr[i] + d) = arr[i + 1] - arr[i]. Note that the answer is a sequence of positive elements of a + a sequence of negative elements of a (i.e., ... +1 +1 +1 +1 -1 -1 ..., as the mountain first increases and then decreases). To solve this problem it's enough to take the tree segments and store at each vertex response to the prefix, suffix, and the middle. Two segments [l; m] and [m + 1; r] can be merged in case sign(a[m + 1]) ≤ sign(a[m]) and they are not equal to zero.
suffix + 1 + 1 + 1 + 1 - 1 - 1 - 1 - 1 и - 1 - 1 - 1 - 1 can be merged with prefix - 1 - 1 - 1 - 1
suffix + 1 + 1 + 1 + 1 can be merged with prefix - 1 - 1 - 1 - 1 or prefix + 1 + 1 + 1 + 1 - 1 - 1 - 1 - 1
译文:
让我们考虑数组中两个相邻元素的差值:a[i] = arr[i + 1] - arr[i] (arr即为题中的初始塔高度)。让我们将区间[l, r]加上 d。显然, 数组 a 将有不超过两个值发生改变(位于区间的两个端点),因为 假若 l < i < r ,那么 a[i] = arr[i + 1] + d - (arr[i] + d) = arr[i + 1] - arr[i] 。注意到答案是由a中一段正数序列和一段负数序列组成(例如,... +1 +1 +1 +1 -1 -1 ... , 因为山顶先上升后下降)。为了解决这个问题, 构造一颗线段树, 每个结点储存相应区间的前缀prefix, 后缀suffix, 以及中值middle。 两个区间[l; m] 和[m+1; r]能合并 当且仅当 sign(a[m + 1]) ≤ sign(a[m]) && a[m] != 0 && a[m+1] != 0
注意:线段树要开4*N!
- #include <cstdio>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- const int maxn = 3e5 + ;
- typedef long long LL;
- int arr[maxn];
- LL a[maxn];
- int n, m;
- int max_suf[*maxn], max_pre[*maxn], max_wid[*maxn];
- int sign(LL x) {return x < ? - : ;}
- int S(int i, int j) {return j - i + ;}
- int p;
- int upd_wid(int o, int L, int R) {
- int M = L + (R-L)/;
- if(L == R) return max_wid[o] = a[L] ? : ;
- else {
- int w1, w2, w3;
- if(p <= M) {
- w1 = upd_wid(*o, L, M);
- w2 = max_wid[*o+];
- }
- else {
- w1 = max_wid[*o];
- w2 = upd_wid(*o+, M+, R);
- }
- w3 = a[M] && a[M+] && sign(a[M+]) <= sign(a[M]) ? S(max_suf[*o], M) + S(M+, max_pre[*o+]) : ;
- int ans = max(w1, w2);
- ans = max(ans, w3);
- return max_wid[o] = ans;
- }
- }
- int upd_suf(int o, int L, int R) {
- int M = L + (R-L)/;
- if(L == R) return max_suf[o] = L;
- else {
- int s1, s2;
- if(p <= M) {
- s1 = upd_suf(*o, L, M);
- s2 = max_suf[*o+];
- }
- else {
- s2 = upd_suf(*o+, M+, R);
- s1 = max_suf[*o];
- }
- int ans = s2;
- if(s2 == M+ && a[M] && a[M+] && sign(a[M+]) <= sign(a[M])) ans = s1;
- return max_suf[o] = ans;
- }
- }
- int upd_pre(int o, int L, int R) {
- int M = L + (R-L)/;
- if(L == R) return max_pre[o] = L;
- else {
- int p1, p2;
- if(p <= M) {
- p1 = upd_pre(*o, L, M);
- p2 = max_pre[*o+];
- }
- else {
- p2 = upd_pre(*o+, M+, R);
- p1 = max_pre[*o];
- }
- int ans = p1;
- if(p1 == M && a[M] && a[M+] && sign(a[M+]) <= sign(a[M])) ans = p2;
- return max_pre[o] = ans;
- }
- }
- int main() {
- scanf("%d", &n);
- for(int i = ; i <= n; i++) scanf("%d", &arr[i]);
- for(int i = ; i < n; i++) {
- a[i] = arr[i+] - arr[i];
- p = i;
- upd_pre(, , n-);
- upd_suf(, , n-);
- upd_wid(, , n-);
- }
- scanf("%d", &m);
- for(int i = ; i <=m; i++) {
- int l, r, v;
- scanf("%d%d%d", &l, &r, &v);
- int wid;
- if(n != ) {
- p = l-;
- a[l-] += v;
- upd_pre(, , n-);
- upd_suf(, , n-);
- upd_wid(, , n-);
- p = r;
- a[r] -= v;
- upd_pre(, , n-);
- upd_suf(, , n-);
- upd_wid(, , n-);
- wid = max_wid[]+;
- }
- else wid = ;
- printf("%d\n", wid);
- }
- return ;
- }
codeforce 381 div2的更多相关文章
- codeforce 192 div2解题报告
今天大家一起做的div2,怎么说呢,前三题有点坑,好多特判.... A. Cakeminator 题目的意思是说,让你吃掉cake,并且是一行或者一列下去,但是必须没有草莓的存在.这道题目,就是判断一 ...
- codeforces Round#381 div2
第一题: 按余数分类,1,2,3分别由哪些基数组成 1->[1][2+3][3+3+3] 2->[1+1][2][3+3] 3->[1+1+1][1+2][3] #include&l ...
- Codeforce 287 div2 C题
题目链接:http://codeforces.com/contest/507/problem/C 解题报告:现在有一个满二叉树型的迷宫,入口在根结点,出口在第n个叶节点,有一串命令,LRLRLRLRL ...
- codeforce #339(div2)C Peter and Snow Blower
Peter and Snow Blower 题意:有n(3 <= n <= 100 000)个点的一个多边形,这个多边形绕一个顶点转动,问扫过的面积为多少? 思路:开始就认为是一个凸包的问 ...
- Codeforce 220 div2
D 插入: 在当前指针位置sz处插入一个1,col[sz]记录插入的内容,sz++; 删除i: 找到第i个1的位置,赋为0; 于是转化为一个维护区间和的问题; trick: 如果是依次删除a[0],a ...
- Codeforce 218 div2
D 一开始想错了,试图用"前缀和-容量"来求从上层流下来了多少水",但这是错的,因为溢出可能发生在中间. 然后发现对于每层,溢出事件只会发生一次,所以可以用类似并查集的办 ...
- Codeforce 217 div2
C 假设每种颜色的个数都相同,可以用轮换的方式,让答案达到最大n,当不同的时候,可以每次从每种颜色中取出相同个数的手套来操作; 一直迭代下去直到只剩下1种颜色; 再将这一种颜色与之前交换过的交换就行了 ...
- Codeforce 216 div2
D 只要搞清楚一个性质:确定了当前最大和次大的位置,局面就唯一确定了; 根据这个性质设计dp,统计到达该局面的方法数即可. E 询问的要求是: 求有多少个区间至少覆盖了询问的点集中的一个; 转化成逆命 ...
- Codeforces #381(div2)
A.题目:http://codeforces.com/contest/740/problem/A 题意:现有n本书,买一本书需要花a元,两本书b元,三本书c元,问买够书是4的倍数所需要的最小花费 思路 ...
随机推荐
- PHP学习(语言结构语句)
switch case语句 for循环语句: foreach循环语句 常用于遍历数组,一般有两种使用方式:不取下标.取下标. (1)只取值,不取下标 <?php foreach (数组 as 值 ...
- Thrift源码分析(一)-- 基本概念
我所在的公司使用Thrift作为基础通信组件,相当一部分的RPC服务基于Thrift框架.公司的日UV在千万级别,Thrift很好地支持了高并发访问,并且Thrift相对简单地编程模型也提高了服务地开 ...
- Struts → 《Struts2程序开发》教材大纲
- Oracle安装 卸载 和常见问题
Oracle的安装 全局数据库名:orcl 口令:orcl 或者以第三方工具SQLplus为例 系统用户:sys 和 system 练习账户:scott (密码:tiger) 登录账户为:sy ...
- SDUT-2124_基于邻接矩阵的广度优先搜索遍历
数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...
- core文件相关
1:当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像.core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的. 当程序接收到以下UNIX信号会产生core文件: ...
- 【Linux】gnuplot命令大全
gnuplot命令大全 在linux命令提示符下运行gnuplot命令启动,输入quit或q或exit退出. plot命令 gnuplot> plot sin(x) with line line ...
- mysql LIMIT 子句用法及原理
使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,已 经为我们提供了这样一个功能. LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接 ...
- 数组工具类 Day07
package com.sxt.arraytest2; /* * 数组的工具类 */ import java.util.Arrays; public class TestArrays { public ...
- Java练习 SDUT-1689_斐波那契?
斐波那契? Time Limit: 1000 ms Memory Limit: 32768 KiB Problem Description 给出一个数列的递推公式,希望你能计算出该数列的第N个数.递推 ...