假设我们可以对每个位置快速维护一个数组,记录每个位置有哪些值是已经出现了的,哪些值是没有出现的,这样就可以决定修改的时候到底是 *2 还是 +1了。

但是很可惜,并不存在功能这么强大的数组,所以只能另寻方法啦。。。。

因为修改总是连续的一段的,所以我们可以发现,对于每个数值来说,被它覆盖的位置也是一段一段的,并且所有数的段数之和<=总的操作数(因为还会发生一些段的合并)。

所以我们可以对每个数维护一个端点集合set,每次修改的时候就暴力插入一段区间,看一看可以产生多少次合并。

这样的话,虽然一次修改的复杂度可能会十分之大,但是因为一个端点在贡献一次合并之后就被从 set 里删去了(一次合并只会对应线段树中的一次区间修改),并且每次最多增加两个端点,所以可以证明最后总的复杂度是 O( M * log (N) ),常数略大。。。

(并且用set维护每个数的区间的时候细节特别多,一定要想清楚了再去写)

(rank 22/212)

Discription

In the School of Magic in Dirtpolis a lot of interesting objects are studied on Computer Science lessons.

Consider, for example, the magic multiset. If you try to add an integer to it that is already presented in the multiset, each element in the multiset duplicates. For example, if you try to add the integer 22 to the multiset {1,2,3,3}{1,2,3,3}, you will get {1,1,2,2,3,3,3,3}{1,1,2,2,3,3,3,3}.

If you try to add an integer that is not presented in the multiset, it is simply added to it. For example, if you try to add the integer 44 to the multiset {1,2,3,3}{1,2,3,3}, you will get {1,2,3,3,4}{1,2,3,3,4}.

Also consider an array of nn initially empty magic multisets, enumerated from 11 to nn.

You are to answer qq queries of the form "add an integer xx to all multisets with indices l,l+1,…,rl,l+1,…,r" and "compute the sum of sizes of multisets with indices l,l+1,…,rl,l+1,…,r". The answers for the second type queries can be large, so print the answers modulo 998244353998244353.

Input

The first line contains two integers nn and qq (1≤n,q≤2⋅1051≤n,q≤2⋅105) — the number of magic multisets in the array and the number of queries, respectively.

The next qq lines describe queries, one per line. Each line starts with an integer tt(1≤t≤21≤t≤2) — the type of the query. If tt equals 11, it is followed by three integers ll, rr, xx (1≤l≤r≤n1≤l≤r≤n, 1≤x≤n1≤x≤n) meaning that you should add xx to all multisets with indices from ll to rr inclusive. If tt equals 22, it is followed by two integers ll, rr (1≤l≤r≤n1≤l≤r≤n) meaning that you should compute the sum of sizes of all multisets with indices from ll to rr inclusive.

Output

For each query of the second type print the sum of sizes of multisets on the given segment.

The answers can be large, so print them modulo 998244353998244353.

Examples

Input
4 4
1 1 2 1
1 1 2 2
1 1 4 1
2 1 4
Output
10
Input
3 7
1 1 1 3
1 1 1 3
1 1 1 2
1 1 1 1
2 1 1
1 1 1 2
2 1 1
Output
4
8

Note

In the first example after the first two queries the multisets are equal to [{1,2},{1,2},{},{}][{1,2},{1,2},{},{}], after the third query they are equal to [{1,1,2,2},{1,1,2,2},{1},{1}][{1,1,2,2},{1,1,2,2},{1},{1}].

In the second example the first multiset evolves as follows:

{}→{3}→{3,3}→{2,3,3}→{1,2,3,3}→{1,1,2,2,3,3,3,3}{}→{3}→{3,3}→{2,3,3}→{1,2,3,3}→{1,1,2,2,3,3,3,3}.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200005,ha=998244353;
#define lc (o<<1)
#define mid (l+r>>1)
#define rc ((o<<1)|1)
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
struct node{
int p,id;
bool operator <(const node &u)const{
return p==u.p?id<u.id:p<u.p;
}
};
set<node> s[maxn];
set<node> :: iterator it,her;
int d[maxn*4],tag[maxn*4],sum[maxn*4];
int n,m,Q,le,ri,w,len[maxn*4],ans,opt; inline void maintain(int o){ sum[o]=add(sum[lc],sum[rc]);} inline void work(int o,int der){
ADD(tag[o],der);
ADD(sum[o],der*(ll)len[o]%ha);
} inline void mul(int o,int der){
d[o]=d[o]*(ll)der%ha;
tag[o]=tag[o]*(ll)der%ha;
sum[o]=sum[o]*(ll)der%ha;
} inline void pushdown(int o){
if(d[o]!=1){
mul(lc,d[o]),mul(rc,d[o]);
d[o]=1;
} if(tag[o]){
work(lc,tag[o]),work(rc,tag[o]);
tag[o]=0;
}
} void build(int o,int l,int r){
d[o]=1,len[o]=r-l+1;
if(l==r) return;
build(lc,l,mid);
build(rc,mid+1,r);
} void umul(int o,int l,int r){
if(l>=le&&r<=ri){ mul(o,2); return;}
pushdown(o);
if(le<=mid) umul(lc,l,mid);
if(ri>mid) umul(rc,mid+1,r);
maintain(o);
} void uadd(int o,int l,int r){
if(l>=le&&r<=ri){ work(o,w); return;}
pushdown(o);
if(le<=mid) uadd(lc,l,mid);
if(ri>mid) uadd(rc,mid+1,r);
maintain(o);
} void query(int o,int l,int r){
if(l>=le&&r<=ri){ ADD(ans,sum[o]); return;}
pushdown(o);
if(le<=mid) query(lc,l,mid);
if(ri>mid) query(rc,mid+1,r);
} void Change(int num,int L,int R){
set<node> &S=s[num]; int fl=L,fr=R; it=S.lower_bound((node){L,0}); for(w=1;L<=R;it=S.lower_bound((node){L,0})){
if(it==S.end()){
le=L,ri=R,uadd(1,1,n);
break;
}
else if(it->id){
le=L,ri=min(it->p,R),umul(1,1,n);
L=ri+1;
if(R>=it->p) S.erase(it);
}
else{
le=L,ri=min(it->p-1,R);
if(le<=ri) uadd(1,1,n);
L=ri+1;
if(R>=it->p) S.erase(it);
}
} it=S.lower_bound((node){fl,0});
her=S.lower_bound((node){fr,1}); if(it==S.begin()||(--it)->id) S.insert((node){fl,0});
if(her==S.end()||!her->id) S.insert((node){fr,1});
} inline void solve(){
build(1,1,n); while(Q--){
scanf("%d",&opt);
if(opt==1){
scanf("%d%d%d",&le,&ri,&w);
Change(w,le,ri);
}
else{
scanf("%d%d",&le,&ri),ans=0;
query(1,1,n),printf("%d\n",ans);
}
}
} int main(){
scanf("%d%d",&n,&Q);
solve();
return 0;
}

  

CodeForces - 981G Magic multisets的更多相关文章

  1. Codeforces 710C. Magic Odd Square n阶幻方

    C. Magic Odd Square time limit per test:1 second memory limit per test:256 megabytes input:standard ...

  2. Codeforces 670D1. Magic Powder - 1 暴力

    D1. Magic Powder - 1 time limit per test: 1 second memory limit per test: 256 megabytes input: stand ...

  3. [递推+矩阵快速幂]Codeforces 1117D - Magic Gems

    传送门:Educational Codeforces Round 60 – D   题意: 给定N,M(n <1e18,m <= 100) 一个magic gem可以分裂成M个普通的gem ...

  4. CodeForces 670D2 Magic Powder 二分

    D2. Magic Powder - 2 The term of this problem is the same as the previous one, the only exception — ...

  5. 【模拟】Codeforces 710C Magic Odd Square

    题目链接: http://codeforces.com/problemset/problem/710/C 题目大意: 构造一个N*N的幻方.任意可行解. 幻方就是每一行,每一列,两条对角线的和都相等. ...

  6. codeforces 632F. Magic Matrix

    题目链接 给一个n*n的矩阵, 问是否对角线上的元素全都为0, a[i][j]是否等于a[j][i], a[i][j]是否小于等于max(a[i][k], a[j][k]), k为任意值. 前两个都好 ...

  7. CodeForces - 710C Magic Odd Square(奇数和幻方构造)

    Magic Odd Square Find an n × n matrix with different numbers from 1 to n2, so the sum in each row, c ...

  8. Codeforces 632F Magic Matrix(bitset)

    题目链接  Magic Matrix 考虑第三个条件,如果不符合的话说明$a[i][k] < a[i][j]$ 或 $a[j][k] < a[i][j]$ 于是我们把所有的$(a[i][j ...

  9. codeforces C. Magic Formulas 解题报告

    题目链接:http://codeforces.com/problemset/problem/424/C 题目意思:给出 n 个数:p1, p2, ..., pn,定义: q1 = p1 ^ (1 mo ...

随机推荐

  1. 【BZOJ 1647】[Usaco2007 Open]Fliptile 翻格子游戏 模拟、搜索

    第一步我们发现对于每一个格子,我们只有翻和不翻两种状态,我们发现一旦确定了第一行操作,那么第二行的操作也就随之确定了,因为第一行操作之后我们要想得到答案就得把第一行全部为0,那么第二行的每一个格子的操 ...

  2. codevs 1078 最小生成树 kruskal

    题目描述 Description 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 约翰已经给他的农场安排了一条高速的网络线路,他想把这 ...

  3. 通用adapter

    http://blog.csdn.net/lmj623565791/article/details/38902805/

  4. vs tip1

    纠结了两个小时在ivtc上,最后得出结论:别用ffms2打开m2ts,要用lsmas.LWLibavSource...

  5. org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.oskyhang.gbd.service.UserService] found for dependency: expected at least 1 bean which qualifies as aut

    spring中一个符号的错误居然让我浪费了四五个小时才找出来,不得不给自己了两个耳光.. 由于新建项目与原来项目的目录结构有所不同,copy过来的配置文件,有些地方修改的不彻底,导致spring扫描注 ...

  6. Spring学习--xml 中 Bean 的自动装配

    Spring IOC 容器可以自动装配 Bean. 只要在 <bean> 的 autowire 属性里指定自动装配的模式. byName(根据名称自动装配):必须将目标 Bean 的名称和 ...

  7. 使用jQuery发送POST,Ajax请求返回JSON格式数据

    问题: 使用jQuery POST提交数据到PHP文件, PHP返回的json_encode后的数组数据,但jQuery接收到的数据不能解析为JSON对象,而是字符串{"code" ...

  8. java封装的使用

    一:前言 其实以前我们来学习java特性的时候,对于封装好想觉得没什么用处,至少我那个时候的感觉(不知道是不是我学的太浅薄了~),现在由于项目从零开始做得,在做得过程中我感觉到原来封装是这样用的. 二 ...

  9. 关于flume的几道题

    1,要求:监听一个tcp,udp端口41414将数据打印在控制台 # example.conf: A single-node Flume configuration # Name the compon ...

  10. NYOJ 115 城市平乱 (最短路)

    * 题目链接* 描述 南将军统领着N个部队,这N个部队分别驻扎在N个不同的城市. 他在用这N个部队维护着M个城市的治安,这M个城市分别编号从1到M. 现在,小工军师告诉南将军,第K号城市发生了暴乱,南 ...