\(\text{Solution}\)

简要的口胡

线段树维护合法左端点数量

正序枚举 \(i\),将其视为右端点,去除不合法的左端点,统计贡献

再将其视为中间点,由它产生的左端点在线段树上区间加

注意到一个重复出现的 \(b\) 值,上一个相同位置的贡献不能再要

于是把这个点废掉

考场上又打了棵线段树,统计答案的线段树只需去掉被废掉的点即可

直接跑了 \(949ms\),两只 \(\text{log}\) 踩线过(后时限开到 \(2s\),不算踩线了,可仍然垫底)

\(\text{Code}\)

#include <cstdio>
#include <algorithm>
#define ls (p << 1)
#define rs (ls | 1)
#define re register
#define LL long long
using namespace std; const int N = 2e5 + 5;
int n, b[N], l1[N], l2[N];
LL ans; int sum[N << 2], tag[N << 2], del[N << 2]; inline void remove(int p, int l, int r, int x)
{
if (x < l || x > r) return;
if (l == r) return void(del[p] = 1);
int mid = (l + r) >> 1;
if (x <= mid) remove(ls, l, mid, x);
else remove(rs, mid + 1, r, x);
del[p] = del[ls] + del[rs];
}
inline int count(int p, int l, int r, int x, int y)
{
if (x > y || y < l || x > r) return 0;
if (x <= l && r <= y) return del[p];
int mid = (l + r) >> 1, res = 0;
if (x <= mid) res = count(ls, l, mid, x, y);
if (y > mid) res += count(rs, mid + 1, r, x, y);
return res;
} inline void pushdown(int p, int l, int r)
{
if (!tag[p]) return;
int mid = (l + r) >> 1;
sum[ls] += (mid - l + 1 - count(1, 1, n, l, mid)) * tag[p], tag[ls] += tag[p];
sum[rs] += (r - mid - count(1, 1, n, mid + 1, r)) * tag[p], tag[rs] += tag[p];
tag[p] = 0;
}
void update(int p, int l, int r, int x, int y, int v)
{
if (x > y || y < l || x > r) return;
if (x <= l && r <= y)
{
sum[p] += v * (r - l + 1 - count(1, 1, n, l, r)), tag[p] += v;
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if (x <= mid) update(ls, l, mid, x, y, v);
if (y > mid) update(rs, mid + 1, r, x, y, v);
sum[p] = sum[ls] + sum[rs];
}
int query(int p, int l, int r, int x, int y)
{
if (x > y || y < l || x > r) return 0;
if (x <= l && r <= y) return sum[p];
pushdown(p, l, r);
int mid = (l + r) >> 1, res = 0;
if (x <= mid) res = query(ls, l, mid, x, y);
if (y > mid) res += query(rs, mid + 1, r, x, y);
return res;
} int main()
{
scanf("%d", &n);
for(re int i = 1; i <= n; i++) scanf("%d", &b[i]);
for(re int i = 1; i <= n; i++)
{
update(1, 1, n, l2[b[i]] + 1, l1[b[i]] - 1, -1);
update(1, 1, n, l1[b[i]], l1[b[i]], -query(1, 1, n, l1[b[i]], l1[b[i]]));
remove(1, 1, n, l1[b[i]]), ans += query(1, 1, n, l1[b[i]] + 1, i - 2);
update(1, 1, n, l1[b[i]] + 1, i - 1, 1), l2[b[i]] = l1[b[i]], l1[b[i]] = i;
}
printf("%lld\n", ans);
}

其实只需将第二个线段树改为树状数组,尽管还是两只 \(\text{log}\),但快了很多

\(\text{Code}\)

#include <cstdio>
#include <algorithm>
#define ls (p << 1)
#define rs (ls | 1)
#define re register
#define LL long long
using namespace std; const int N = 2e5 + 5;
int n, b[N], l1[N], l2[N], c[N];
LL ans; int sum[N << 2], tag[N << 2], del[N << 2]; inline int lowbit(int x){return x & (-x);}
inline void remove(int x, int v)
{
if (!x) return;
for(; x <= n; x += lowbit(x)) c[x] += v;
}
inline int querysum(int x)
{
if (!x) return 0;
int res = 0;
for(; x; x -= lowbit(x)) res += c[x];
return res;
}
inline int count(int x, int y){return querysum(y) - querysum(x - 1);} inline void pushdown(int p, int l, int r)
{
if (!tag[p]) return;
int mid = (l + r) >> 1;
sum[ls] += (mid - l + 1 - count(l, mid)) * tag[p], tag[ls] += tag[p];
sum[rs] += (r - mid - count(mid + 1, r)) * tag[p], tag[rs] += tag[p];
tag[p] = 0;
}
void update(int p, int l, int r, int x, int y, int v)
{
if (x > y || y < l || x > r) return;
if (x <= l && r <= y)
{
sum[p] += v * (r - l + 1 - count(l, r)), tag[p] += v;
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if (x <= mid) update(ls, l, mid, x, y, v);
if (y > mid) update(rs, mid + 1, r, x, y, v);
sum[p] = sum[ls] + sum[rs];
}
int query(int p, int l, int r, int x, int y)
{
if (x > y || y < l || x > r) return 0;
if (x <= l && r <= y) return sum[p];
pushdown(p, l, r);
int mid = (l + r) >> 1, res = 0;
if (x <= mid) res = query(ls, l, mid, x, y);
if (y > mid) res += query(rs, mid + 1, r, x, y);
return res;
} int main()
{
scanf("%d", &n);
for(re int i = 1; i <= n; i++) scanf("%d", &b[i]);
for(re int i = 1; i <= n; i++)
{
update(1, 1, n, l2[b[i]] + 1, l1[b[i]] - 1, -1);
update(1, 1, n, l1[b[i]], l1[b[i]], -query(1, 1, n, l1[b[i]], l1[b[i]]));
remove(l1[b[i]], 1), ans += query(1, 1, n, l1[b[i]] + 1, i - 2);
update(1, 1, n, l1[b[i]] + 1, i - 1, 1), l2[b[i]] = l1[b[i]], l1[b[i]] = i;
}
printf("%lld\n", ans);
}

其实要在线段树上废掉一个点,只要将这个线段树带上系数,把这一位系数改成 \(0\) 即可

\(Code\)

#include <cstdio>
#include <algorithm>
#define ls (p << 1)
#define rs (ls | 1)
#define re register
#define LL long long
using namespace std; const int N = 2e5 + 5;
int n, b[N], l1[N], l2[N];
LL ans; int sum[N << 2], tag[N << 2], c[N << 2];
inline void pushdown(int p, int l, int r)
{
if (!tag[p]) return;
int mid = (l + r) >> 1;
sum[ls] += c[ls] * tag[p], tag[ls] += tag[p];
sum[rs] += c[rs] * tag[p], tag[rs] += tag[p];
tag[p] = 0;
}
inline void change(int p, int l, int r, int x, int v)
{
if (x < l || x > r) return;
if (l == r)
{
c[p] = v, sum[p] = v * tag[p];
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if (x <= mid) change(ls, l, mid, x, v);
else change(rs, mid + 1, r, x, v);
sum[p] = sum[ls] + sum[rs], c[p] = c[ls] + c[rs];
}
void update(int p, int l, int r, int x, int y, int v)
{
if (x > y || y < l || x > r) return;
if (x <= l && r <= y)
{
sum[p] += v * c[p], tag[p] += v;
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if (x <= mid) update(ls, l, mid, x, y, v);
if (y > mid) update(rs, mid + 1, r, x, y, v);
sum[p] = sum[ls] + sum[rs], c[p] = c[ls] + c[rs];
}
int query(int p, int l, int r, int x, int y)
{
if (x > y || y < l || x > r) return 0;
if (x <= l && r <= y) return sum[p];
pushdown(p, l, r);
int mid = (l + r) >> 1, res = 0;
if (x <= mid) res = query(ls, l, mid, x, y);
if (y > mid) res += query(rs, mid + 1, r, x, y);
return res;
} int main()
{
scanf("%d", &n);
for(re int i = 1; i <= n; i++) scanf("%d", &b[i]);
for(re int i = 1; i <= n; i++)
{
update(1, 1, n, l2[b[i]] + 1, l1[b[i]] - 1, -1), change(1, 1, n, l1[b[i]], 0);
ans += query(1, 1, n, l1[b[i]] + 1, i - 2);
update(1, 1, n, l1[b[i]] + 1, i - 1, 1), change(1, 1, n, i, 1);
l2[b[i]] = l1[b[i]], l1[b[i]] = i;
}
printf("%lld\n", ans);
}

【USACO 2021 US Open, Platinum】United Cows of Farmer John的更多相关文章

  1. 孤独的照片【USACO 2021 December Contest Bronze】

    孤独的照片 Farmer John 最近购入了 \(N\) 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一. 奶牛目前排成一排,Farmer John 想要为 ...

  2. 洛谷 P2812 校园网络【[USACO]Network of Schools加强版】 解题报告

    P2812 校园网络[[USACO]Network of Schools加强版] 题目背景 浙江省的几所OI强校的神犇发明了一种人工智能,可以AC任何题目,所以他们决定建立一个网络来共享这个软件.但是 ...

  3. P2812 校园网络【[USACO]Network of Schools加强版】

    题目背景 浙江省的几所OI强校的神犇发明了一种人工智能,可以AC任何题目,所以他们决定建立一个网络来共享这个软件.但是由于他们脑力劳动过多导致全身无力身体被♂掏♂空,他们来找你帮助他们. 题目描述 共 ...

  4. luogu P2812 校园网络【[USACO]Network of Schools加强版】|Tarjan

    题目背景 浙江省的几所OI强校的神犇发明了一种人工智能,可以AC任何题目,所以他们决定建立一个网络来共享这个软件.但是由于他们脑力劳动过多导致全身无力身体被♂掏♂空,他们来找你帮助他们. 题目描述 共 ...

  5. 【USACO 2.1.1】城堡

    [题目描述] 我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票).结果这张彩票让他获得了这次比赛唯一的奖品— ...

  6. 【USACO】草地排水

    Drainage Ditches 草地排水 usaco 4.2.1描述在农夫约翰的农场上,每逢下雨,Bessie最喜欢的三叶草地就积聚了一潭水.这意味着草地被水淹没了,并且小草要继续生长还要花相当长一 ...

  7. POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)

    POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...

  8. 题解 【USACO 4.2.1】草地排水

    [USACO 4.2.1]草地排水 Description 在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水.这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间.因此,农夫 ...

  9. 1642: 【USACO】Payback(还债)

    1642: [USACO]Payback(还债) 时间限制: 1 Sec 内存限制: 64 MB 提交: 190 解决: 95 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 &quo ...

  10. 1519: 【USACO】超级书架

    1519: [USACO]超级书架 时间限制: 1 Sec 内存限制: 64 MB 提交: 1735 解决: 891 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 Farmer Jo ...

随机推荐

  1. EasyCode全自动单表增删改查!

    需要IDEA下载EasyCode插件 准备好三个基础Base类 分页封装基础 package com.gton.io; import lombok.AllArgsConstructor; import ...

  2. 2.10:数据加工与展示-pandas清洗、Matplotlib绘制

    〇.目标 1. 使用pandas完成基本的数据清洗加工处理: 2. 使用Matplotlib进行简单的数据图形化展示. 一.用pandas清洗处理数据 1.判断是否存在空值 数据缺失在很多数据中存在, ...

  3. 【Scala】上:学习文档、文章、思维导图

    〇.可查阅资料 1.文档 英文文档:https://tool.oschina.net/apidocs/apidoc?api=scala-docs-2.9.2 与java:https://docs.sc ...

  4. 5V升压8.4V,5V转8.4芯片电路图

    PW5300是电流模式升压DC-DC转换器.其内置0.2Ω功率MOSFET的PWM电路使该稳压器具有效高的功率效率.内部补偿网络还可以程度地减少了6个外部元件的数量.误差放大器的同相输入接到0.6V精 ...

  5. choices参数

    目录 一:choices参数 1.choices参数作用 2.列举: 3.choices效果 二:choices使用 1.创建字段类型 2.验证choices 3.使用测试脚本 4.将manage.p ...

  6. frp内网穿透(已验证)

    # 云服务器frp内网穿透教程 软件源码在https://github.com/fatedier/frp/releases上,根据系统类型,按需下载 教程术语描述 > A 是有固定IP的云服务器 ...

  7. uniapp 微信小程序 引入 环信聊天

    最近项目需要实现一个聊天的功能,群聊或者单聊,用到环信,根据官网实现一下相关的配置吧 第一:下载环信demo  地址:https://github.com/easemob/webim-uniapp-d ...

  8. [seaborn] seaborn学习笔记11-绘图实例(3) Drawing example(3)

    11 绘图实例(3) Drawing example(3)(代码下载) 本文主要讲述seaborn官网相关函数绘图实例.具体内容有: Plotting a diagonal correlation m ...

  9. 一文详解RocketMQ的存储模型

    摘要:RocketMQ 优异的性能表现,必然绕不开其优秀的存储模型. 本文分享自华为云社区<终于弄明白了 RocketMQ 的存储模型>,作者:勇哥java实战分享. RocketMQ 优 ...

  10. Vue 修改对象(数组)没有立即生效

    在写项目时遇到了给数组赋值后,出现赋值延时的问题,解决办法如下 // Vue 不能检测以下变动的数组: // 当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = ne ...