2016北京集训测试赛(十七)Problem C: 数组
Solution
线段树好题.
我们考虑用last[i]
表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \le j} last[j]\).
而我们的答案就等于
\]
第一项可以直接计算, 考虑如何维护第二项.
我们开一颗线段树, 假设一个节点所维护的区间是\([L, R]\), 则节点维护\(\sum_{i = L}^R max_{L \le j \le i} last[j]\). 具体怎么实现, 看代码即可.
#include <cstdio>
#include <cctype>
#include <set>
#include <algorithm>
#define iter set<int>::iterator
using namespace std;
namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1; char c;
while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
const int N = (int)1e5;
int n;
int col[N + 1], pre[N + 1];
set<int> st[N + 1];
inline iter getPrevious(iter p) {return -- p;}
inline iter getNext(iter p) {return ++ p;}
struct segmentTree
{
struct node
{
int mx;
long long sum;
}nd[N << 2];
long long work(int u, int L, int R, int val)
{
int mid = L + R >> 1;
if(L == R) {return max(val, nd[u].mx);}
else if(nd[u].mx <= val) {return (long long)(R - L + 1) * val;}
else if(nd[u << 1].mx <= val) return (long long)val * (mid - L + 1) + work(u << 1 | 1, mid + 1, R, val);
else return work(u << 1, L, mid, val) + nd[u].sum - nd[u << 1].sum;
}
inline void pushUp(int u, int L, int R)
{
int mid = L + R >> 1;
nd[u].mx = max(nd[u << 1].mx, nd[u << 1 | 1].mx);
nd[u].sum = (long long)nd[u << 1].sum + work(u << 1 | 1, mid + 1, R, nd[u << 1].mx);
}
void build(int u, int L, int R)
{
if(L == R) {nd[u].mx = nd[u].sum = pre[L]; return;}
int mid = L + R >> 1;
build(u << 1, L, mid); build(u << 1 | 1, mid + 1, R);
pushUp(u, L, R);
}
inline void build() {build(1, 1, n);}
void modify(int u, int L, int R, int pos, int val)
{
if(L == R) {nd[u].sum = nd[u].mx = val; return;}
int mid = L + R >> 1;
if(pos <= mid) modify(u << 1, L, mid, pos, val); else modify(u << 1 | 1, mid + 1, R, pos, val);
pushUp(u, L, R);
}
inline void modify(int pos, int val) {modify(1, 1, n, pos, val);}
}seg;
int main()
{
#ifndef ONLINE_JUDGE
freopen("array.in", "r", stdin);
freopen("array.out", "w", stdout);
#endif
using namespace Zeonfai;
n = getInt();
for(int i = 1; i <= n; ++ i) st[i].clear();
for(int i = 1; i <= n; ++ i)
{
col[i] = getInt();
if(st[col[i]].empty()) pre[i] = 0; else pre[i] = *getPrevious(st[col[i]].find(i));
st[col[i]].insert(i);
}
seg.build();
int m = getInt();
for(int i = 0; i < m; ++ i)
{
int opt = getInt();
if(opt)
{
int pos = getInt(), x = getInt();
iter p = getNext(st[col[pos]].find(pos));
st[col[pos]].erase(st[col[pos]].find(pos));
if(p != st[col[pos]].end()) pre[*p] = p == st[col[pos]].begin() ? 0 : *getPrevious(p);
if(p != st[x].end()) seg.modify(*p, pre[*p]);
col[pos] = x; st[x].insert(pos);
pre[pos] = st[x].find(pos) == st[x].begin() ? 0 : *getPrevious(st[x].find(pos));
p = getNext(st[x].find(pos)); if(p != st[x].end()) pre[*p] = pos;
if(p != st[x].end()) seg.modify(*p, pre[*p]);
seg.modify(pos, pre[pos]);
}
else printf("%lld\n", (long long)n * (n + 1) / 2 - seg.nd[1].sum);
}
}
2016北京集训测试赛(十七)Problem C: 数组的更多相关文章
- [2016北京集训测试赛7]isn-[树状数组+dp+容斥]
Description Solution 定义dp[i][j]为在1到i个数中选了j个数,并且保证选了i的选法总数. dp[i][j]为所有满足A[k]>A[i]的k(k<i)的dp[k] ...
- 2016北京集训测试赛(十七)Problem B: 银河战舰
Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
- 2016北京集训测试赛(十七)Problem A: crash的游戏
Solution 相当于要你计算这样一个式子: \[ \sum_{x = 0}^m \left( \begin{array}{} m \\ x \end{array} \right) \left( \ ...
- 2016北京集训测试赛(十六)Problem C: ball
Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sq ...
- 2016北京集训测试赛(十六)Problem B: river
Solution 这题实际上并不是构造题, 而是一道网络流. 我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样. ...
- 2016北京集训测试赛(十六)Problem A: 任务安排
Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...
- BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记
Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...
- 2016北京集训测试赛(十四)Problem B: 股神小D
Solution 正解是一个\(\log\)的link-cut tree. 将一条边拆成两个事件, 按照事件排序, link-cut tree维护联通块大小即可. link-cut tree维护子树大 ...
- 2016北京集训测试赛(十四)Problem A: 股神小L
Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格 ...
随机推荐
- JVM内存管理:深入Java内存区域与OOM
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...
- unknow table alarmtemp error when drop database (mysql)
Q: unknow table alarmtemp error when drop database (mysql) D: alarmtemp is table in rtmd database. ...
- cf984c Finite or not?
一个十进制分数 \(p/q\) 在 \(b\) 进制下是有限小数的充要条件是 \(q\) 的所有质因子都是 \(b\) 的质因子. First, if \(p\) and \(q\) are not ...
- apizza导出为html后,从中提取api_name/api_path/api_method,保存到本地,方便根据接口名称得到接口路径与请求方法
import re import os def open_file(file='c:/newcrm.html'): f=open(file,'r',encoding='utf-8') return f ...
- Python学习-day13 SqlAlchemy
本节内容 ORM介绍 sqlalchemy安装 sqlalchemy基本使用 多外键关联 多对多关系 表结构设计作业 1. ORM介绍 orm英文全称object relational mapping ...
- Python数据分析基础——读写CSV文件2
2.2筛选特定的行: 行中的值满足某个条件 行中的值属于某个集合 行中的值匹配于某个模式(即:正则表达式) 2.2.1:行中的值满足于某个条件: 基础python版: #!/usr/bin/env p ...
- 聊聊、RabbitMQ 配置文件
windows 下面安装 rabbitMQ 比较简单,但是想去改端口相关信息却找不到配置文件在哪.Linux 在 /etc/rabbitmq/rabbitmq.config 下面就可以找到.来看看 w ...
- 【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- 求中位数为K的区间的数目
给定一个长为 $n$ 的序列和常数 $k$,求此序列的中位数为 $k$ 的区间的数量.一个长为 $m$ 的序列的中位数定义为将此序列从小到大排序后第 $\lceil m / 2 \rceil$ 个数. ...
- BZOJ 4069 [Apio2015]巴厘岛的雕塑 ——贪心
自己首先想了一种方法$f(i)$表示前$i$个最小值为多少. 然而发现位运算并不满足局部最优性. 然后我们可以从高到低贪心的判断,使得每一组的和在一个特定的范围之内. 还要特判最后一个Subtask, ...