[Avito Code Challenge 2018 G] Magic multisets(线段树)
题目链接:http://codeforces.com/contest/981/problem/G
题目大意:
有n个初始为空的‘魔法’可重集,向一个‘可重集’加入元素时,若该元素未出现过,则将其加入;否则该可重集中所有元素的个数都会翻倍。
例如将$2$加入${1,3}$会得到${1,2,3}$,将$2$加入${1,2,3,3}$会得到${1,1,2,2,3,3,3,3}$.
$q$次操作,每次操作要么向一个区间内的所有可重集加入某个元素,要么询问一个区间内可重集的大小之和。
$n,q ≤ 2×10^5$
题解:
发现对于出现过该元素的区间就是区间乘,没有出现过的就是区间加
操作1我们先把$[l,r]$全部乘上2,再把之前已经出现过当前元素的区间乘上2的逆元再+1,最后合并一下左右区间就好了。合并大概就是保证这个操作时间复杂度的关键了,只是我也不知道怎么算
发现这样我们要维护每个元素出现的区间,同时支持方便的合并,我们开n个set就好了
正是做完这题我发现我竟然不会写区间乘法线段树
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<set>
#define pa pair<int,int>
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll; const int N=2e5+;
const int mod=;
ll n,q,inv;
ll sum[N<<],add[N<<],mul[N<<];
set <pa> st[N];
inline ll read()
{
char ch=getchar();
ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
ll qpow(ll a,ll b)
{
ll re=;
for (;b;b>>=,a=a*a%mod) if (b&) re=re*a%mod;
return re;
}
void build(int o,int l,int r)
{
mul[o]=;add[o]=sum[o]=;
if (l==r) return;
build(o<<,l,mid);
build(o<<|,mid+,r);
}
void pushup(int o,int l,int r)
{
//sum[o]=sum[o<<1]+sum[o<<1|1];
sum[o]=(sum[o<<]*mul[o<<]+add[o<<]*(mid-l+))%mod;
sum[o]=(sum[o]+sum[o<<|]*mul[o<<|]+add[o<<|]*(r-mid))%mod;
}
void pushdown(int o,int l,int r)
{
if (mul[o]!=)
{
ll p=mul[o];
mul[o]=;
//(sum[o<<1]*=p)%=mod;
//(sum[o<<1|1]*=p)%=mod;
(add[o<<]*=p)%=mod;
(add[o<<|]*=p)%=mod;
(mul[o<<]*=p)%=mod;
(mul[o<<|]*=p)%=mod;
}
if (add[o]!=)
{
ll p=add[o];
add[o]=;
// (sum[o<<1]+=p*(mid-l+1))%=mod;
// (sum[o<<1|1]+=p*(r-mid))%=mod;
(add[o<<]+=p)%=mod;
(add[o<<|]+=p)%=mod;
}
}
void update(int o,int l,int r,int x,int y,ll z,int flag)
{
if (l>=x&&r<=y)
{
if (flag==)
{
(mul[o]*=z)%=mod;
(add[o]*=z)%=mod;
// (sum[o]*=z)%=mod;
}
if (flag==)
{
(add[o]+=z)%=mod;
// (sum[o]+=(r-l+1)*z)%=mod;
}
return;
}
pushdown(o,l,r);
if (x<=mid) update(o<<,l,mid,x,y,z,flag);
if (y>mid) update(o<<|,mid+,r,x,y,z,flag);
pushup(o,l,r);
}
void merge(int x,int L,int R)
{
set<pa>::iterator it;
it=st[x].lower_bound(pa(L,L));
for (;it!=st[x].end();it++)
{
set<pa>::iterator lst=it;lst--;
int l=(*lst).second+;
int r=(*it).first-;
int upl=max(L,l);
int upr=min(R,r);
if (upr>=upl)
{
update(,,n,upl,upr,inv,);
update(,,n,upl,upr,,);
}
if ((*it).first>=R) break;
}
int mergeL=L,mergeR=R;
it=st[x].upper_bound(pa(L,L));it--;
if ((*it).second>=mergeL) mergeL=(*it).first;
it=st[x].upper_bound(pa(R,R));it--;
if ((*it).second>=mergeR) mergeR=(*it).second;
vector <pa> er;
it=st[x].lower_bound(pa(mergeL,mergeL));
for (;it!=st[x].end();it++)
{
pa e=*it;
if (e.first>=mergeL&&e.second<=mergeR) er.push_back(e);
else break;
}
for (int i=;i<er.size();i++) st[x].erase(er[i]);
st[x].insert(pa(mergeL,mergeR));
}
ll query(int o,int l,int r,int x,int y)
{
if (l>=x&&r<=y) return (sum[o]*mul[o]+add[o]*(r-l+))%mod;
// if (l>=x&&r<=y) return sum[o]%mod;
pushdown(o,l,r);
ll re=;
if (x<=mid) (re+=query(o<<,l,mid,x,y))%=mod;
if (y>mid) (re+=query(o<<|,mid+,r,x,y))%=mod;
pushup(o,l,r);
return re;
}
int main()
{
inv=qpow(,mod-);
//inv=(mod+1)/2;
n=read();q=read();
for (int i=;i<=n;i++)
{
st[i].insert(pa(,));
st[i].insert(pa(n+,n+));
}
build(,,n);
while (q--)
{
int opt=read();
if (opt==)
{
int l=read(),r=read(),z=read();
update(,,n,l,r,,);
merge(z,l,r);
}
if (opt==)
{
int l=read(),r=read();
printf("%lld\n",query(,,n,l,r));
}
}
return ;
}
[Avito Code Challenge 2018 G] Magic multisets(线段树)的更多相关文章
- Codeforces Avito Code Challenge 2018 D. Bookshelves
Codeforces Avito Code Challenge 2018 D. Bookshelves 题目连接: http://codeforces.com/contest/981/problem/ ...
- Codeforces - Avito Code Challenge 2018
Portal A. Antipalindrome 暴力. B. Businessmen Problems 暴力. C. Useful Decomposition 居然不是C打头的?! 将一棵树划分成若 ...
- Avito Code Challenge 2018 C
C. Useful Decomposition time limit per test 1 second memory limit per test 256 megabytes input stand ...
- Avito Code Challenge 2018 A~E
A. Antipalindrome 还以为是什么神dp结果就是分情况讨论啊 原串是一串一样的字符的话输出0,是回文串的话输出n-1,否则直接输出原串长度 #include<iostream> ...
- cf掉分记——Avito Code Challenge 2018
再次作死的打了一次cf的修仙比赛感觉有点迷.. 还好掉的分不多(原本就太低没法掉了QAQ) 把会做的前三道水题记录在这.. A: Antipalindrome emmmm...直接暴力枚举 code: ...
- Avito Code Challenge 2018
第一次打CF,很菜,A了三道水题,第四题好像是是数位DP,直接放弃了.rateing从初始的1500变成了1499,还是绿名,这就很尴尬.之后觉得后面的题目也没有想象的那么难(看通过人数)过两天吧剩下 ...
- BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流
BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流 Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1 ...
- ACM-ICPC 2018 徐州赛区网络预赛-G Trace(线段树的应用
Problem:Portal传送门 Problem:Portal传送门 原题目描述在最下面. 我理解的题意大概是:有n次涨潮和退潮,每次的范围是个x×y的矩形,求n次涨退潮后,潮水痕迹的长度. ...
- 【Codeforces717F】Heroes of Making Magic III 线段树 + 找规律
F. Heroes of Making Magic III time limit per test:3 seconds memory limit per test:256 megabytes inpu ...
随机推荐
- poj--3169--Layout(简单差分约束)
Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9098 Accepted: 4347 Descriptio ...
- PHP 上传文件到其他服务器
PHP 上传文件到其他服务器 标签(空格分隔): 安装Guzzle类库 **guzzle** 是发送网络请求的类库 composer安装:**composer require guzzlehttp/g ...
- MySQL 我自己常用的语句汇总
1,更新,根据一个表更新另一个表,比如批量同步外键 方法一: update 更新表 set 字段 = (select 参考数据 from 参考表 where 参考表.id = 更新表.id); up ...
- javascript中缓存
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 在应用层通过spring特性解决数据库读写分离
如何配置mysql数据库的主从? 单机配置mysql主从:http://my.oschina.net/god/blog/496 常见的解决数据库读写分离有两种方案 1.应用层 http://neore ...
- 在centos上安装php5.5+MySQL 5.5.32
在centos直接使用yum install 安装php的话版本比较低,如果需要高版本的话,请看如下: Step 1: Installing Remi Repository ## Install Re ...
- swfupload组件上传文件
前段时间做文件上传用的是H5的一个插件,由于浏览器的兼容性不好,所以又换了一个Flash版本的上传文件插件,感觉这个上传插件的使用方式跟H5的差不多,有些雷同.不过,由于后续浏览不再支持Flash(略 ...
- canvas 画图优化
http://www.cnblogs.com/rhcad/archive/2012/11/17/2774794.html
- css——应用多个样式
应用多个样式 在class中使用多个样式 在这是会有优先级关系问题 在上面的代码中,aa,bb,中的颜色会有冲突,到底显示的结果会是黄色还是绿色呢? 结果是绿色的.它是以程序执行的先后为优先级,后执行 ...
- Python数据分析3------数据预处理(2)----字符串处理