- qinkaiwen 的博客
题解:CF1552F Telepanting
- @ 2026-7-22 20:12:53
做题时间:2026.7.22 题目难度:2200 | 题目链接 | 洛谷链接
我居然半小时才做完?
挺有趣的一道思维题。(这又不是计数题为什么要取模?)
首先这道题的每一个区间一旦使用就会多产生 的时间(重走一遍),然后将状态重新设为 。所以这道题其实是求每段区间被使用的次数,是计数题,所以要取模。
所以如果状态全是 那就都得走,至于 这个状态只是让你逃课的。
所以这题除了最终计算与状态没有半毛钱关系。
我又发现一个区间被使用很可能会导致其他区间被相应使用。
考虑令 为区间 在使用后所产生的总时间(包括因此被使用的其他区间),易发现 ,其中 是所有满足 的下标。(真的容易发现吗?)
然后就要递归计算?其实并不用,因为 是按顺序排列的,所以所有满足性质的 早就在之前的计算中算好了,二分加前缀和即可。
另外还有一个性质也同理,即当你要使用一个区间时,这个区间内的所有满足性质的区间都是开启状态。原因很简单,你已经在它关闭的时候走过它了。
剩下的就不用说了,看代码吧。
#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;
}