题目大意:

给定$n$个序列,要你从每个序列中选一个非空子串然后拼起来,拼成的序列的贡献为不同元素个数。

支持单点修改,在开始时和每次修改完后,输出所有不同选取方案的贡献和。

解题思路:

窝又来切Ynoi辣

STL题。

考虑每种元素的贡献,相当于求出有多少种方案包含这个数。补集转化成有多少种方案不包含这个数。

求有多少种方案不包含这个数,就相当于求每个序列有多少子区间不包含这个数,然后乘法原理。

而求有多少子区间不包含这个数,就相当于用这个数把序列分成若干区间,每个区间内部可以任意选取。

用一个数组存每种数有多少方案不包含,用map存每个序列里每种数有多少方案不包含,对每种数开个set存其位置。

插入的时候,相当于把一个大区间分裂成两个小区间,在set里查找前驱后继,更新map里的值即可。同时更新数组里的值和答案。删除的时候同理。

注意当一个序列只有一种数的时候,map里值为0,所以需要特殊处理一下,打个标记。

时间复杂度$O((n+m)\log n)$。

C++ Code:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<iostream>
using namespace std;
typedef pair<int,int>pii;
const int md=19260817,N=2e5+5;
typedef long long LL;
int L[N],R[N],bel[N],len[N],a[N],n,m,inv[300005],LN[N],Ynoi=1,ept[N],P[N];
int ans=0;
set<int>s[N];
map<pii,int>gx;
vector<int>lr;
struct opts{
int x,y,z;
}q[N];
inline int C2(int len){return(len*(len-1LL)>>1)%md;}
inline int INV(int i){return(i<300000)?inv[i]:((LL)md-md/i)*INV(md%i)%md;}
void insert(int col,int pos){
int pre=*--s[col].lower_bound(pos),suf=*s[col].upper_bound(pos);
pre=max(pre,L[bel[pos]]-1),suf=min(suf,R[bel[pos]]+1);
const pii xb=make_pair(bel[pos],col);
if(!gx.count(xb))gx[xb]=C2(len[bel[pos]]+1);
int&v=gx[xb];
ans=(ans+((ept[col])?0:LN[col]))%md;
LN[col]=(LL)LN[col]*INV(v)%md;
v=(v-C2(suf-pre)+C2(pos-pre)+C2(suf-pos)+md)%md;
if(v)
LN[col]=(LL)LN[col]*v%md;else ++ept[col];
ans=(ans-((ept[col])?0:LN[col])+md)%md;
s[col].insert(pos);
}
void erase(int col,int pos){
int pre=*--s[col].lower_bound(pos),suf=*s[col].upper_bound(pos);
pre=max(pre,L[bel[pos]]-1),suf=min(suf,R[bel[pos]]+1);
const pii xb=make_pair(bel[pos],col);
if(!gx.count(xb))gx[xb]=C2(len[bel[pos]]+1);
int&v=gx[xb];
ans=(ans+((ept[col])?0:LN[col]))%md;
if(!v)--ept[col];else
LN[col]=(LL)LN[col]*INV(v)%md;
v=(v+C2(suf-pre)-C2(pos-pre)-C2(suf-pos)+md+md)%md;
LN[col]=(LL)LN[col]*v%md;
ans=(ans-((ept[col])?0:LN[col])+md)%md;
s[col].erase(pos);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
inv[1]=1;
for(register int i=2;i<300000;++i)inv[i]=((LL)md-md/i)*inv[md%i]%md;
for(int i=1;i<=n;++i)cin>>len[i],L[i]=R[i-1]+1,R[i]=R[i-1]+len[i],Ynoi=(LL)Ynoi*C2(len[i]+1)%md,P[i]=P[i-1]+len[i];
for(int i=1;i<=n;++i)
for(int j=L[i];j<=R[i];++j)bel[j]=i,cin>>a[j],lr.push_back(a[j]);
for(int i=1;i<=m;++i){
cin>>q[i].x>>q[i].y>>q[i].z;
lr.push_back(q[i].z);
}
sort(lr.begin(),lr.end());
lr.erase(unique(lr.begin(),lr.end()),lr.end());
for(int i=0;i<=lr.size();++i)s[i].insert(0),s[i].insert(R[n]+1),LN[i]=Ynoi;
for(int i=1;i<=R[n];++i){
a[i]=lower_bound(lr.begin(),lr.end(),a[i])-lr.begin();
insert(a[i],i);
}
cout<<ans<<'\n';
for(int i=1;i<=m;++i){
const int id=P[q[i].x-1]+q[i].y;
erase(a[id],id);
insert(a[id]=lower_bound(lr.begin(),lr.end(),q[i].z)-lr.begin(),id);
cout<<ans<<'\n';
}
return 0;
}

[Ynoi2016]谁的梦的更多相关文章

  1. 题解 P4692 【[Ynoi2016]谁的梦】

    Ynoi 中少见的不卡常题呢....虽说有 50 个数据点... 果然还是道好题 noteskey 总之就是补集转化的思想,算出每种颜色选点的总方案减去不可行方案(就是不包含 该种颜色的点的区间选取方 ...

  2. P4692 [Ynoi2016]谁的梦

    传送门 分别考虑每一种颜色对答案的贡献.每种颜色的贡献就是他出现的区间个数,那么可以用总区间减去不包含它的区间个数,把每一个序列里不包含它的区间个数加起来,然后不同序列用乘法原理计算即可 于是我辛辛苦 ...

  3. BZOJ 5395--[Ynoi2016]谁的梦(STL&容斥)

    5395: [Ynoi2016]谁的梦 Time Limit: 80 Sec  Memory Limit: 128 MBSubmit: 22  Solved: 7[Submit][Status][Di ...

  4. 一个技术汪的开源梦 —— 基于 .Net Core 的组件 Nuget 包制作 & 发布

    一个技术汪的开源梦 —— 目录 微软的 ASP.Net Core 强化了 Nuget 的使用,所有的 .Net Core 组件均有 Nuget 管理,所以有必要探讨一下 .Net Core 组件制作 ...

  5. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之 Http 请求客户端

    一个技术汪的开源梦 —— 目录 想必大家在项目开发的时候应该都在程序中调用过自己内部的接口或者使用过第三方提供的接口,咱今天不讨论 REST ,最常用的请求应该就是 GET 和 POST 了,那下面开 ...

  6. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之序列化

    一个技术汪的开源梦 —— 目录 想必大家在项目中都接触过 JSON 或者 XML 吧,为了将对象在网络上传输或者将其持久化必须将其序列化为一个字符串然后进行后续操作.常见的就是将其序列化成 JSON ...

  7. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之目录结构

    一个技术汪的开源梦 —— 目录 这篇文章是开源公共组件的开篇那就先说说项目的 Github 目录结构和 .Net Core 的项目结构. 1. GitHub 目录结构和相关文件 - src 源码项目目 ...

  8. 织梦cms常用标签

    dedecms简介:织梦内容管理系统(DedeCms) 以简单.实用.开源而闻名,是国内知名的PHP开源网站管理系统,也是使用用户较多的PHP类CMS系统,在经历多年的发展,目前的版本无论在功能,还是 ...

  9. 织梦Dedecms使用Nginx的安全设置

    首先需要说明的是,任何程序都是有漏洞的,我们需要做好一些必要的防范,来减少由于程序漏洞造成的损失.织梦的漏洞多,这个是很多人的想法.不过大家如果做好了织梦系统的文件夹权限什么的设置,很多漏洞也是用不上 ...

随机推荐

  1. 编程之美初赛第二场AB

    题目1 : 扑克牌 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 一副不含王的扑克牌由52张牌组成,由红桃.黑桃.梅花.方块4组牌组成,每组13张不同的面值.现在给定52 ...

  2. Android学习笔记之:android更新ui的几种经常用法

    Android主线程不能运行耗时操作.我们通常是在子线程中运行耗时操作, 我们在运行完耗时操作后,我们一般能够通过下面几种方式来实现ui界面的更新. 首先是布局文件: <LinearLayout ...

  3. HDU 4259(Double Dealing-lcm(x1..xn)=lcm(x1,lcm(x2..xn))

    Double Dealing Time Limit: 50000/20000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. 3.CCFadeOutTRTiles,部落格效果,跳动的方块特效,3D瓷砖晃动特效,破碎的3D瓷砖特效,瓷砖洗牌特效,分多行消失特效,分多列消失特效

     1 TiledGrid3D //TiledGrid3D //CCFadeOutTRTiles * action = CCFadeOutTRTiles::create(2, CCSize(20,2 ...

  5. 267C

    二分+高斯消元 我们利用物理里的势能来表示,每个点有一个势能h,再由流量守恒可以得到deg[x]*h[x]=sigma(h[y]) 如果x,y之间有边.这个式子是由流量守恒推出的,所以当x=1或n是不 ...

  6. Java压缩技术(二) ZIP压缩——Java原生实现

    原文:http://snowolf.iteye.com/blog/642298 去年整理了一篇ZLib算法Java实现(Java压缩技术(一) ZLib),一直惦记却没时间补充.今天得空,整理一下ZI ...

  7. 延时提示框制作思路[简单javascript案例]

    模拟QQ软件中的弹出提示框功能,制作一个简易的延时提示框. 功能实现: 1.当鼠标移入指定区块时,弹出隐藏的区块:当鼠标移出指定区块时,弹出的隐藏区块再次隐藏. 2.同时要求在鼠标移入该弹出区块后,区 ...

  8. Cracking the Coding Interview 8.7

    Given a infinite number of quarters(25cents), dimens(10cents), nickels(5cents) and pennies(1cent), w ...

  9. [Luogu 2216] [HAOI2007]理想的正方形

    [Luogu 2216] [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输 ...

  10. Spring Boot (1) 构建第一个Spring Boot工程

    Spring boot简介 spring boot是spring官方推出的一个全新框架,其设计目的是用来简化新spring应用的初始搭建以及开发过程. Spring boot特点 1.化繁为简,简化配 ...