[HDU]Glad You Came【ST表】

>Link

hdu 6356


>Description

一个长度为 n n n,初始全部值都为 0 的数组
给出 m m m 次操作,每次操作把 [ l , r ] [l,r] [l,r] 内所有小于 x x x 的数修改成 x x x
求出最终的数组

n ≤ 5 ∗ 1 0 5 , m ≤ 5 ∗ 1 0 7 n\le 5*10^5,m\le5*10^7 n5105,m5107


>解题思路

看到 m m m 的大小, O ( m l o g n ) O(mlogn) O(mlogn)是会TLE的
用ST表,把每次修改的区间 [ l , r ] [l,r] [l,r] 分成两个ST表上的区间(这两个区间可以重叠),在上边标记一下,这样修改为 O ( 1 ) O(1) O(1)
最后我们再把每个标记往下传,记录最大值(根据题意,每个点上的值为所有修改的最大值)
时间复杂度 O ( m + n l o g n ) O(m+nlogn) O(m+nlogn)


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
#define rg register
typedef unsigned int uint;
using namespace std;

int n, m, st[N][30], lg[N], p[N], l, r, x, ll, g, ii;
uint X, Y, Z, W, K;

inline int read ()
{
	int ret = 0;
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9')
	{
		ret = ret * 10 + c - '0';
		c = getchar();
	}
	return ret;
}
inline void write (int x)
{
	if (x < 10) {putchar (x + '0'); return;}
	write (x / 10);
	putchar (x % 10 + '0');
}
inline uint READ()
{
    X = X ^ (X << 11);
    X = X ^ (X >> 4);
    X = X ^ (X << 5);
    X = X ^ (X >> 14);
    W = X ^ Y ^ Z;
    X = Y;
    Y = Z;
    Z = W;
    return Z;
}

int main()
{
//	freopen ("check.out", "w", stdout);
	n = read(), m = read();
	X = read(), Y = read(), Z = read(), K = read();
	p[0] = 1;
	for (rg int i = 1; i <= 20; i++) p[i] = p[i - 1] * 2;
    for (rg int i = 1; i <= n; i++)
	  lg[i] = lg[i - 1] + (p[lg[i - 1]] == i);
    for (rg int i = 1; i <= n; i++) lg[i]--;
	for (rg int i = 1; i <= m; i++)
	{
        l = READ() % n + 1, r = READ() % n + 1, x = READ() % K;
        if (l > r)
        {
        	l = l ^ r;
        	r = l ^ r;
        	l = l ^ r;
		}
		g = lg[r - l + 1];
		st[l][g] = max (st[l][g], x);
		ll = r - p[g] + 1;
		st[ll][g] = max (st[ll][g], x);
    }
    for (rg int j = lg[n]; j >= 1; j--)
      for (rg int i = 1; i <= n - p[j] + 1; i++)
      {
		if (!st[i][j]) continue;
		st[i][j - 1] = max (st[i][j - 1], st[i][j]);
		ii = i + p[j - 1];
		st[ii][j - 1] = max (st[ii][j - 1], st[i][j]);
	  }
    for (rg int i = 1; i <= n; i++)
      write (st[i][0]), putchar (' ');
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值