ZROI1153 【线上训练3】数个数

传送门

一道非常有意思的题,涵盖了各种知识点。

首先,很显然,这是个容斥。容斥可以过掉\(30pts\)。

这里我们考虑容斥+DP。

我们令\(dp[i][j]\)代表对于前\(i\)个区间(区间排过序),上一个取的区间为\(j\)的方案数。

那么每次转移就是:

\[dp[i+1][i+1]+=-dp[i][k]*(s^{len})\space (k<i+1)
\]

其中\(len\)是这两个区间的中间部分的长度。而负号代表容斥系数(长度+1,奇偶性改变,所以变成负的)。

这个\(dp\)相当于考虑了第\(i+1\)个区间接在以不同的区间结尾的方案后面,所以可以做到不重不漏。因为在一种方案后接上一个区间对答案多出的贡献取决于这个区间和上个区间之间的距离,所以只用像这样记录上个区间即可。

下面这份代码来自An_Account,能展示出\(n^2\)的\(dp\)过程:

#include <bits/stdc++.h>
using namespace std;
const int N = 200010, mod = 998244353;
struct Query {
int l, r, b;
bool operator < (const Query &b) const {
return r < b.r || (r == b.r && l < b.l);
}
} l[N];
int dp[N];
typedef long long LL;
inline int Pow(int x, int y) {
int res = 1;
for (; y; y >>= 1, x = (LL)x * x % mod) if (y & 1) res = (LL)res * x % mod;
return res;
}
int main() {
int n, m, s; scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= m; i++) scanf("%d%d%d", &l[i].l, &l[i].r, &l[i].b);
sort(l + 1, l + m + 1);
dp[0] = 1;
for (int i = 1; i <= m; i++)
for (int j = 0; j < i; j++) {
if (l[j].r < l[i].l || l[j].b == l[i].b) {
int t = (LL)dp[j] * Pow(s, max(0, l[i].l - l[j].r - 1)) % mod;
dp[i] = (dp[i] - t + mod) % mod;
}
}
int res = Pow(s, n);
for (int i = 1; i <= m; i++)
res = (res + (LL)dp[i] * Pow(s, n - l[i].r)) % mod;
printf("%d\n", res);
}

而正解就是在他的基础上用线段树优化转移。

首先我们发现满足转移要求有两种情况:

  1. 颜色不相同,区间不相交
  2. 颜色相同

我们考虑分开考虑两种情况,

对于第一种情况,我们可以开一个前缀和。

\[令i,j为两个区间的编号,i在j之后。\\
c[i]=\sum _{j.r<i.l} \frac{dp[j]}{s^{j.r+1}}
\]

这是因为上一个方程中的\(s^{len}\)可以这样转化:

\(s^{len}=s^{r-l+1}=\frac{s^{r+1}}{s^l}\)

因为对于一次转移,\(s^{r+1}\)都是一样的(都是当前区间的起始点),所以我们只要在\(dp[i]=-c[i]*s^{i.l}\)

然后把这个值插入在区间的右端点+1即可(查询的时候查询左端点)。

对于第二种情况,我们可以使用动态开点线段树。

因为在第一种情况里只少统计了颜色相等,区间重叠的情况。所以我们用线段树统计这种情况。

两个区间相交当且仅当第一个区间(前面的区间)的终点被第二个区间包含。那我们统计一下第二个区间内有多少个其他区间的右端点即可。因为两个区间重叠,所以在这一步只有一种方案,所以直接加上上个区间的\(dp\)值即可。(别忘了要取相反数)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
const int mod=998244353;
const int maxn=2e5+1000;
int n,m,s,ls[maxn*80],rs[maxn*80],idx,rt[maxn];
struct gg {
int l,r,b;
}q[maxn];
ll c[maxn],sum[maxn*80],dp[maxn];
void update_t(int loc,int val) {
for(int i=loc;i<=n;i+=i&-i)c[i]+=val,c[i]%=mod;
}
void push_up(int root) {
sum[root]=0;
if(ls[root])sum[root]+=sum[ls[root]];
if(rs[root])sum[root]+=sum[rs[root]];
sum[root]%=mod;
}
void update_s(int l,int r,int root,int val,int tar) {
if(l==r){sum[root]=val;sum[root]%=mod;return;}
int mid=(l+r)>>1;
if(tar<=mid) {
if(!ls[root])ls[root]=++idx;
update_s(l,mid,ls[root],val,tar);
}
if(tar>=mid+1) {
if(!rs[root])rs[root]=++idx;
update_s(mid+1,r,rs[root],val,tar);
}
push_up(root);
}
ll query_t(int loc) {
ll tot=0;for(int i=loc;i;i-=i&-i)tot+=c[i],tot%=mod;
return tot;
}
ll query_s(int l,int r,int root,int tl,int tr) {
if(tl<=l&&r<=tr)return sum[root];
int mid=(l+r)>>1;ll tot=0;
if(l<=mid&&ls[root])tot+=query_s(l,mid,ls[root],tl,tr);
if(r>=mid+1&&rs[root])tot+=query_s(mid+1,r,rs[root],tl,tr);
return tot%mod;
}
int ksm(int num,int t){
int res=1;
for(;t;t>>=1,num=(ll)num*num%mod) {
if(t&1)res=(ll)res*num%mod;
}
return res;
}
vector<gg>col[maxn];
bool cop1(gg x,gg y){if(x.l==y.l)return x.r<y.r;return x.l>y.l;}
bool cop2(gg x,gg y){return x.l<y.l;}
int main() {
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].b);
col[q[i].b].push_back(q[i]);
}
m=0;
for(int i=1;i<=s;i++) {
sort(col[i].begin(),col[i].end(),cop1);
int now=maxn;
for(int j=0;j<col[i].size();j++) {
if(col[i][j].r<now){q[++m]=col[i][j];now=col[i][j].r;}
}
}
sort(q+1,q+1+m,cop2);
dp[0]=1*ksm(s,mod-2);
update_t(1,dp[0]);//初始化
for(int i=1;i<=m;i++) {
ll t=query_t(q[i].l)*ksm(s,q[i].l);t%=mod;
if(rt[q[i].b])t+=query_s(1,n,rt[q[i].b],q[i].l,q[i].r);
dp[i]=(-t)%mod;
update_t(q[i].r+1,(dp[i]*ksm(ksm(s,q[i].r+1),mod-2)%mod));
if(!rt[q[i].b])rt[q[i].b]=++idx;
update_s(1,n,rt[q[i].b],dp[i],q[i].r);
}
ll ans=0;
for(int i=1;i<=m;i++) {
ans+=dp[i]*ksm(s,n-q[i].r);ans%=mod;
}
ans+=ksm(s,n);
ans=(ans%mod+mod)%mod;
printf("%lld",ans);
return 0;
}

ZROI1153 【线上训练3】数个数的更多相关文章

  1. 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

    17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...

  2. 排查Java线上服务故障的方法和实例分析

    前言 作为在线系统负责人或者是一个技术专家,你可能刚刚接手一个项目就需要处理紧急故障,或者被要求帮忙处理一些紧急的故障,这个时候的情景是: (1)你可能对这个业务仅仅是听说过,而不怎么真正了解: (2 ...

  3. CSDN挑战编程——《金色十月线上编程比赛第二题:解密》

    金色十月线上编程比赛第二题:解密 题目详情: 小强是一名学生, 同一时候他也是一个黑客. 考试结束后不久.他吃惊的发现自己的高等数学科目竟然挂了,于是他果断入侵了学校教务部站点. 在入侵的过程中.他发 ...

  4. 深度学习笔记 (二) 在TensorFlow上训练一个多层卷积神经网络

    上一篇笔记主要介绍了卷积神经网络相关的基础知识.在本篇笔记中,将参考TensorFlow官方文档使用mnist数据集,在TensorFlow上训练一个多层卷积神经网络. 下载并导入mnist数据集 首 ...

  5. cdoj1339郭大侠与线上游戏

    地址:http://acm.uestc.edu.cn/#/problem/show/1339 题目: 郭大侠与线上游戏 Time Limit: 6000/2000MS (Java/Others)    ...

  6. MySQL慢日志线上问题分析及功能优化

    本文来源于数据库内核专栏. MySQL慢日志(slow log)是MySQL DBA及其他开发.运维人员需经常关注的一类信息.使用慢日志可找出执行时间较长或未走索引等SQL语句,为进行系统调优提供依据 ...

  7. “玲珑杯”线上赛 Round #17 河南专场

    闲来无事呆在寝室打打题,没有想到还有中奖这种操作,超开心的 玲珑杯”线上赛 Round #17 河南专场 Start Time:2017-06-24 12:00:00 End Time:2017-06 ...

  8. Arthas - Java 线上问题定位处理的终极利器

    前言 在使用 Arthas 之前,当遇到 Java 线上问题时,如 CPU 飙升.负载突高.内存溢出等问题,你需要查命令,查网络,然后 jps.jstack.jmap.jhat.jstat.hprof ...

  9. 线上Storm的worker,executor,task参数调优篇

    问题引入: 线上最近的数据量越来越大,出现了数据处理延迟的现象,观察storm ui的各项数据,发现有大量的spout失败的情况,如下: ------------------------------- ...

随机推荐

  1. 【MySQL】多表查询&事务&权限管理

    多表查询: 查询语法: select 列名列表 from 表名列表 where.... 例子: 创建部门表 CREATE TABLE dept( id INT PRIMARY KEY AUTO_INC ...

  2. Window权限维持(十):Netsh Helper DLL

    Netsh是Windows实用程序,管理员可以使用它来执行与系统的网络配置有关的任务,并在基于主机的Windows防火墙上进行修改.可以通过使用DLL文件来扩展Netsh功能.此功能使红队可以使用此工 ...

  3. Elasticsearch(ES) 创建索引

    欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...

  4. C 函数声明、函数参数

    参考连接:https://www.runoob.com/cprogramming/c-functions.html 局部变量与全局变量在内存中的储存方式 全局变量保存在内存中的全局储存区中,占用静态的 ...

  5. Vue笔记3

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Fundebug前端异常监控插件更新至 1.9.0,支持监控 HTTP 慢请求

    摘要: 1.9.0新增 httpTimeout 配置选项,支持监控 HTTP 慢请求,同时修复了记录的 HTTP 响应时间偏小的 BUG. Fundebug提供专业的前端异常监控服务,可以第一时间捕获 ...

  7. RPC 初识

    RPC是什么 RPC(Remote Procedure Call) 释义是远程过程调用,常存在于分布式系统中. 比如说现在有两台服务器A, B,一个在A服务器上的应用想要调用B服务器上的应用提供的某个 ...

  8. JVM 对象查询语言(OQL)[转载]

    最近生产环境出现一个很奇怪的问题,测试环境无法重现,本地直连生产无法重现.于是用上 jmap + Java VisualVM 的 OQL (Object Query Language) 分析问题. 关 ...

  9. 201871010101- 陈来弟《面向对象程序设计(java)》第6-7周学习总结

    201871010101- 陈来弟<面向对象程序设计(java)>第6-7周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh ...

  10. 201871010118-唐敬博 《面向对象程序设计(java)》第十五周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 <https://www.cnblogs.com/nwnu-daizh/> 这个作业的要求在哪里 <https://ww ...