做题时间:2026.7.22 题目难度:2200 | 题目链接 | 洛谷链接

我居然半小时才做完?

挺有趣的一道思维题。(这又不是计数题为什么要取模?)

首先这道题的每一个区间一旦使用就会多产生 xyx-y 的时间(重走一遍),然后将状态重新设为 11所以这道题其实是求每段区间被使用的次数,是计数题,所以要取模。

所以如果状态全是 11 那就都得走,至于 00 这个状态只是让你逃课的。

所以这题除了最终计算与状态没有半毛钱关系。

我又发现一个区间被使用很可能会导致其他区间被相应使用。

考虑令 f[i]f[i] 为区间 ii 在使用后所产生的总时间(包括因此被使用的其他区间),易发现 f[i]=xiyi+f[j]f[i]=x_i - y_i +\sum f[j] ,其中 jj 是所有满足 yixjxiy_i \le x_j \le x_i 的下标。(真的容易发现吗?)

然后就要递归计算?其实并不用,因为 xix_i 是按顺序排列的,所以所有满足性质的 jj 早就在之前的计算中算好了,二分加前缀和即可。

另外还有一个性质也同理,即当你要使用一个区间时,这个区间内的所有满足性质的区间都是开启状态。原因很简单,你已经在它关闭的时候走过它了。

剩下的就不用说了,看代码吧。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10,P=998244353;
vector<int>G[N];
struct node{int x,y,c;}a[N];
int b[N],s[N],f[N];
signed main()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y>>a[i].c,b[i]=a[i].x;
	for(int i=1;i<=n;i++)
	{
		int pos=upper_bound(b+1,b+n,a[i].y)-b;
		f[i]=((s[i-1]-s[pos-1]+a[i].x-a[i].y)%P+P)%P;
		s[i]=(s[i-1]+f[i])%P;
	}
	int ans=(a[n].x+1)%P;
	for(int i=1;i<=n;i++)if(a[i].c)ans=(ans+f[i])%P;
	cout<<ans;
	return 0;
}