F. Intersection and Union (线段树, 矩阵维护dp)

//https://codeforces.com/contest/1743/problem/F
#include<bits/stdc++.h>
#include<unordered_map>
#include<array>
#define ll long long
#define ull unsigned long long
#define all(a) a.begin(),a.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;

const int inf = 2e9 + 2;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-4;
const ll mod = 998244353;
const int N = 3e5 + 5;

#define int ll
const int K = 2;
struct Matrix {
	ll a[K][K];
	Matrix() {}
	void clear() { memset(a, 0, sizeof a); }//变成0矩阵
	void init()//初始化为单位阵
	{
		clear();
		for (int i = 0; i < K; i++)
			a[i][i] = 1;
	}
	Matrix operator * (const Matrix& x) const
	{
		Matrix res;
		res.clear();
		for (int i = 0; i < K; i++)
			for (int j = 0; j < K; j++)
				for (int k = 0; k < K; k++)
					(res.a[i][j] += a[i][k] * x.a[k][j] % mod) %= mod;
		return res;
	}
	Matrix operator + (const Matrix& x) const
	{
		Matrix res;
		res.clear();
		for (int i = 0; i < K; i++)
			for (int j = 0; j < K; j++)
				res.a[i][j] = (a[i][j] + x.a[i][j]) % mod;
		return res;
	}
};

int n, L, R;
struct node {
	int l, r;
	Matrix lazy, sum;
}tree[N << 2];

void push_up(int p)
{
	tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum;
}

void build(int l, int r, int p)
{
	tree[p] = { l, r };
	tree[p].lazy.init();
	tree[p].sum.clear();
	if (l == r)
	{
		if (l < L || r > R)
			tree[p].sum.a[0][0] = 1;
		else
			tree[p].sum.a[1][0] = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, p << 1);
	build(mid + 1, r, p << 1 | 1);
	push_up(p);
}

inline void push_down(int p)
{
	tree[p << 1].lazy = tree[p].lazy * tree[p << 1].lazy;
	tree[p << 1].sum = tree[p].lazy * tree[p << 1].sum;
	tree[p << 1 | 1].lazy = tree[p].lazy * tree[p << 1 | 1].lazy;
	tree[p << 1 | 1].sum = tree[p].lazy * tree[p << 1 | 1].sum;
	tree[p].lazy.init();
}

void update(int ul, int ur, Matrix val, int p)
{
	int l = tree[p].l, r = tree[p].r;
	if (ul <= l && ur >= r)
	{
		tree[p].lazy = val * tree[p].lazy;
		tree[p].sum = val * tree[p].sum;
		return;
	}
	push_down(p);
	int mid = (l + r) / 2;
	if (ul <= mid)
		update(ul, ur, val, p << 1);
	if (ur > mid)
		update(ul, ur, val, p << 1 | 1);
	push_up(p);
}

void solve()
{
	cin >> n;
	cin >> L >> R;
	build(0, 3e5, 1);
	Matrix mat1;
	mat1.a[0][0] = mat1.a[0][1] = 1;
	mat1.a[1][0] = mat1.a[1][1] = 2;
	Matrix mat2;
	mat2.a[0][0] = 3;
	mat2.a[0][1] = 1;
	mat2.a[1][0] = 0;
	mat2.a[1][1] = 2;
	for (int i = 2, l, r; i <= n; i++)
	{
		cin >> l >> r;
		if (l > 0)
			update(0, l - 1, mat2, 1);
		if (r < 3e5)
			update(r + 1, 3e5, mat2, 1);
		update(l, r, mat1, 1);
	}

	cout << tree[1].sum.a[1][0] << '\n';
}

signed main()
{
	IOS;
	int t = 1;
	//cin >> t;
	while (t--)
		solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值