首页 > 其他分享 >题解 P9130 【[USACO23FEB] Hungry Cow P】

题解 P9130 【[USACO23FEB] Hungry Cow P】

时间:2023-04-19 16:01:19浏览次数:39  
标签:int 题解 tt Hungry P9130 num ls ans out

赛时开始一眼线段树分治,交了几发都 T 了,就意识到事情不对。后来想了想发现势能分析不能带撤销。。。

后来加了一些不能改变复杂度假了的优化,没过之后就自闭跑路了。。。

赛后听别人说了个楼房重建就明白怎么做了。

首先,我们离线下来把 \(a\) 排序,去重(这样方便一点,不然权值线段树上的空节点得特判),线段树的叶子节点表示的是 \([t_i,t_{i+1})\) 这段区间。为了方便,我们设 \(t_{n+1}=\inf\)。

我们维护当前线段树区间的 \(4\) 个值:

  1. 总共匹配了多少个值;
  2. 总共向右超出了多少个值;
  3. 匹配的答案是多少;
  4. 左区间超出部分的答案,若左区间超出部分在右区间依旧超出,那就不管了。

考虑 pushup,分 \(2\) 种情况:

  1. 左区间超出部分在右区间依旧超出,则右区间被填满了;
  2. 左区间超出部分都可以在右区间插入,我们在右区间做线段树二分,计算出最后一个左区间超出部分的位置。由于需要减掉原始匹配的答案所以具体实现时需要维护 4(在 pushup 的时候记一下)。

写的时候刚睡醒,一个地方 +- 打反了,调了半年。

代码很短:

#include <bits/stdc++.h>
#define ls num << 1
#define rs ls | 1
#define li ls, l, mid
#define ri rs, mid + 1, r
#define int long long
#define SZ(x) (int) x.size() - 1
#define all(x) x.begin(), x.end()
#define ms(x, y) memset(x, y, sizeof x)
#define F(i, x, y) for (int i = (x); i <= (y); i++)
#define DF(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) { x = max(x, y); }
template <typename T> void chkmin(T &x, T y) { x = min(x, y); }
template <typename T> void read(T &x) {
	x = 0; int f = 1; char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
const int N = 1e5 + 10, MOD = 1e9 + 7, inv2 = (MOD + 1) / 2;
int rt, tot, x[N], y[N], t[N];
int qq(int l, int r) {
	return ((r - l + 1) % MOD) * ((l + r) % MOD) % MOD * inv2 % MOD;
}
struct seg {
	int out, sum, ans, lans;
} tt[N * 4];
pair <int, int> query(int num, int l, int r, int x) {
	if (l == r) return make_pair(t[l] + tt[num].sum + x - 1, tt[num].ans);
	int mid = (l + r) >> 1;
	int cnt = t[mid + 1] - t[l] - tt[ls].sum;
	if (x <= cnt) return query(ls, l, mid, x);
	pair <int, int> ans = query(rs, mid + 1, r, x - cnt + tt[ls].out);
	ans.second += tt[ls].ans + tt[num].lans;
	return ans;
}
void pushup(int num, int l, int r) {
	int mid = (l + r) >> 1;
	int cnt = t[r + 1] - t[mid + 1] - tt[rs].sum;
	if (cnt < tt[ls].out) {
		tt[num].out = tt[rs].out + tt[ls].out - cnt;
		tt[num].sum = tt[ls].sum + t[r + 1] - t[mid + 1];
		tt[num].ans = tt[ls].ans + qq(t[mid + 1], t[r + 1] - 1);
		tt[num].lans = -1;
	} else {
		tt[num].out = tt[rs].out;
		tt[num].sum = tt[ls].sum + tt[rs].sum + tt[ls].out;
		pair <int, int> pos = make_pair(t[mid + 1] - 1, 0);
		if (tt[ls].out) pos = query(rs, mid + 1, r, tt[ls].out);
		tt[num].lans = qq(t[mid + 1], pos.first) - pos.second;
		tt[num].ans = tt[ls].ans + tt[rs].ans + tt[num].lans;
	}
}
void change(int num, int l, int r, int x, int y) {
	if (l == r) {
		tt[num].sum = min(y, t[l + 1] - t[l]);
		tt[num].ans = qq(t[l], t[l] + tt[num].sum - 1);
		tt[num].out = y - tt[num].sum;
		return;
	} int mid = (l + r) >> 1;
	if (mid >= x) change(li, x, y);
	else change(ri, x, y);
	pushup(num, l, r);
}
signed main() {
	int n; read(n);
	F(i, 1, n) read(x[i]), read(y[i]), t[i] = x[i];
	sort(t + 1, t + n + 1);
	int m = unique(t + 1, t + n + 1) - t - 1;
	t[m + 1] = 1e18;
	F(i, 1, n) {
		change(1, 1, m, lower_bound(t + 1, t + m + 1, x[i]) - t, y[i]);
		cout << (tt[1].ans % MOD + MOD) % MOD << '\n';
	}
	return 0;
}

标签:int,题解,tt,Hungry,P9130,num,ls,ans,out
From: https://www.cnblogs.com/zhaohaikun/p/17333596.html

相关文章

  • api-ms-win-core-file-l1-2-0.dll文件问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或者损坏了,这时你只需下载这个api-ms-win-core-file-l1-2-0.dll文件进行安装(前提是找到适合的版本),当我们执行某......
  • 2023联合省选题解
    2023联合省选题解火车站签到题。可以发现,一段被覆盖的区间上任意两点联通,因此用差分维护连续段即可。intmain(){n=read(),m=read(),x=read();for(inti=1;i<=m;i++){intl=read(),r=read();bl[l]=1;br[r]=1;c[l]++,c[r+1]--;......
  • Pwn系列之Protostar靶场 Stack6题解
    源码如下:#include<stdlib.h>#include<unistd.h>#include<stdio.h>#include<string.h>voidgetpath(){charbuffer[64];unsignedintret;printf("inputpathplease:");fflush(stdout);gets(buffer);ret=__b......
  • CF题解
    E.ReplacetheNumbers1900思维https://codeforces.com/problemset/problem/1620/E题解:正着做比较困难,我们可以考虑从后往前做。一个数会被变成什么样子是取决于其后的2操作。2操作可以等价为一个变换,而位置越后的2操作相较前面的2操作起着决定性作用,故从后往前遍历时前面的......
  • 【题解】P6292 区间本质不同子串个数
    原题链接区间本质不同子串个数题目描述给定一个长度为\(n\)的字符串\(S\),\(m\)次询问由\(S\)的第\(L\)到第\(R\)个字符组成的字符串包含多少个本质不同的子串。定义两个字符串\(a,b\)相同当且仅当\(|a|=|b|\)并且对于\(i\in[1,|a|]\)都有\(a_i=b_i\)。输入......
  • 超级码力初赛第二场 五字回文 题解
    题目描述小栖最近很喜欢回文串,由于小栖的幸运数字是5,他想知道形似“abcba"的回文串在他给定的字符串中的数量s.length<=10^6字符串s只包含小写字母示例示例1:输入:s="abcba"输出:1示例2:输入:s="abcbabcccb"输出:2解释:形似”abcba“的字符串有”abcba“和”cbab......
  • CF题解
    D.GuessthePermutation2000逆序性质二分https://codeforces.com/contest/1589/problem/D题解:首先我们可以二分查找i的位置:当1->x逆序对>0,则在i右,否则在左,log(n)次询问。找到i的位置后,我们发现逆序对有如下性质,i->j-1的数量和i+1->j-1的数量差为j-1-i,故我们可以询问i+1->n......
  • GDOU-CTF-2023新生赛Pwn题解与反思
    第一次参加CTF新生赛总结与反思因为昨天学校那边要进行天梯模拟赛,所以被拉过去了。16点30分结束,就跑回来宿舍开始写。第一题和第二题一下子getshell,不用30分钟,可能我没想那么多,对比网上的WP,自己和他们有点不太一样,比较暴力。大概17点10的时候,写第三题,可能自己第一次遇到随机数问......
  • elementui select下来内容过长问题解决方案
    :popper-append-to-body="false"必写自定义显示<divclass="select-flow">{{dict.declareConditions}}</div>自定义css样式el-option添加title属性 <el-selectv-model="formData.declCondition"placeholder="请选择"sty......
  • CF1646E Power Board 题解
    题目链接:https://codeforces.com/contest/1646/problem/E题目大意:有一个\(n\timesm\)的矩阵,其中第\(i\)行第\(j\)列的格子中的数字是\(i^j\)。问:矩阵中存在多少个不同的数?解题思路:可以很明显地发现,第\(1\)行的数字全部都是\(1\),而且在其它行不会出现数值为\(1\)......