\(\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. Java Web中requset,session,application 的作用域及区别

    三者概述 requset概述: request是表示一个请求,只要发出一个请求就会创建一个request 用处:常用于服务器间同一请求不同页面之间的参数传递,常应用于表单的控件值传递. session ...

  2. Linux相关命令及软件安装教程

    @font-face { font-family: "Times New Roman" } @font-face { font-family: "宋体" } @ ...

  3. 【每日一题】【递归+int型返回值最后不接收】110. 平衡二叉树-211231/220221

    给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 . 答案: public class Solution ...

  4. 云原生架构(二)环境搭建(Mac上安装Docker+Kubernetes+Istio一条龙)

    一.背景 Istio 项目由 Google 和 IBM 的团队与 Lyft 的 Envoy 团队合作启动.它已经完全在 GitHub 上公开开发.目前已经是"Service Mesh服务网格 ...

  5. Qt网络编程-从0到多线程编程

    网络编程开发 1.简介 两个协议,一个是TCP协议,一个是UDP协议 先说TCP: TCP的话,服务器端需要端口监听,直到有客户端进行连接发送过来请求数据,然后客户端根据请求数据进行应答,之后就算tc ...

  6. 从源码层面深度剖析Spring循环依赖

    作者:郭艳红 以下举例皆针对单例模式讨论 图解参考 https://www.processon.com/view/link/60e3b0ae0e3e74200e2478ce 1.Spring 如何创建 ...

  7. 深度学习之Transformer网络

    [博主使用的python版本:3.6.8] 本次没有额外的资料下载 Packages ort tensorflow as tf import pandas as pd import time impo ...

  8. python进阶之路7 数据类型的内置方法

    内容回顾 while 循环补充说明 1.死循环 2.while循环嵌套和全局标志位 for循环 1.for 变量名 in 待遍历数据 for循环体代码 2.for 也可以与break continue ...

  9. 蓝桥真题——最短路 & 门牌制作

    题目1 最短路 标签:填空题 2019 省赛 如下图所示,G 是一个无向图,其中蓝色边的长度是 1.橘色边的长度是 2.绿色边的长度是 3. 则从 A 到 S 的最短距离是多少? 答案 由图可得,最短 ...

  10. GreenPlum批量授权(PG未测试)

    创建一个自定义function create or replace function grant_all_exec(schema_name varchar,select_or_insert varch ...