【CF1743F】Intersection and Union

1|0题目


题目链接:https://codeforces.com/contest/1743/problem/F
n 个集合,其中第 i 个集合 Si 包含 [li,ri] 中的所有整数。
考虑一个长为 n1 的序列 [op1,op2,,opn1],其中每一个元素都可能是 ,, 的任意一个,求这 3n1 个可能的序列

|(((S1 op1 S2) op2 S3) op3 S4) opn1 Sn|

之和。答案对 998244353 取模。
n3×105;0liri3×105

2|0思路


退役人复健(
考虑每一个整数在最终那 3n1 个式子中的贡献。记 01 序列 ai 表示目前这个整数是否被包含于第 i 个区间。
那么很容易想到 dp。设 f[i][0/1] 表示前 i 个区间经过运算后,这个整数不在集合内 / 在集合内的方案数。
考虑两个 0,1 之间进行位运算的结果,那么

f[i][0]={f[i1][0]×3+f[i1][1]×1 (ai=0)f[i1][0]×1+f[i1][1]×1 (ai=1)

f[i][1]={f[i1][0]×0+f[i1][1]×2 (ai=0)f[i1][0]×2+f[i1][1]×2 (ai=1)

把每个数字都跑一遍 dp,时间复杂度 O(nV)
发现由于每一个集合都是一个区间,也就意味着,从计算数字 i 的贡献转移到数字 i+1 的贡献时,数组 a 均摊只有 O(1) 个位置需要改变,所以只需要搞一个动态 dp 就可以了。
时间复杂度 O(Vlogn)

3|0代码


#include <bits/stdc++.h> using namespace std; const int N=300010,MOD=998244353; int n,ans,L,R; vector<int> v1[N],v2[N]; struct Matrix { int a[2][2]; Matrix() { memset(a,0,sizeof(a)); } friend Matrix operator *(Matrix a,Matrix b) { Matrix c; for (int i=0;i<=1;i++) for (int j=0;j<=1;j++) for (int k=0;k<=1;k++) c.a[i][j]=(c.a[i][j]+1LL*a.a[i][k]*b.a[k][j])%MOD; return c; } }mat; struct SegTree { Matrix f[N*4]; void build(int x,int l,int r) { if (l==r) { f[x].a[0][0]=3,f[x].a[1][0]=1,f[x].a[0][1]=0,f[x].a[1][1]=2; return; } int mid=(l+r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); f[x]=f[x*2]*f[x*2+1]; } void update(int x,int l,int r,int k,int opt) { if (l==r) { if (opt==0) f[x].a[0][0]=3,f[x].a[1][0]=1,f[x].a[0][1]=0,f[x].a[1][1]=2; if (opt==1) f[x].a[0][0]=1,f[x].a[1][0]=1,f[x].a[0][1]=2,f[x].a[1][1]=2; return; } int mid=(l+r)>>1; if (k<=mid) update(x*2,l,mid,k,opt); if (k>mid) update(x*2+1,mid+1,r,k,opt); f[x]=f[x*2]*f[x*2+1]; } }seg; int main() { scanf("%d%d%d",&n,&L,&R); for (int i=2,x,y;i<=n;i++) { scanf("%d%d",&x,&y); v1[x].push_back(i); v2[y+1].push_back(i); } seg.build(1,2,n); for (int i=0;i<=300000;i++) { for (int j=0;j<(int)v1[i].size();j++) seg.update(1,2,n,v1[i][j],1); for (int j=0;j<(int)v2[i].size();j++) seg.update(1,2,n,v2[i][j],0); if (L<=i && R>=i) mat.a[0][0]=0,mat.a[0][1]=1; else mat.a[0][0]=1,mat.a[0][1]=0; mat.a[1][0]=mat.a[1][1]=0; ans=(ans+(mat*seg.f[1]).a[0][1])%MOD; } printf("%d",ans); return 0; }

__EOF__

本文作者stoorz
本文链接https://www.cnblogs.com/stoorz/p/16801998.html
关于博主:菜死了 /fad
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   stoorz  阅读(106)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-10-18 【AGC011E】Increasing Numbers
2021-10-18 【洛谷P5590】赛车游戏
2021-10-18 【CF1586F】Defender of Childhood Dreams
点击右上角即可分享
微信分享提示