HYSBZ 1500 维修数列

本文深入探讨了AI音视频处理领域的最新技术,包括视频分割、语义识别、自动驾驶、AR、SLAM等关键应用。通过详细分析算法原理、实际案例和未来趋势,为读者提供了一个全面的技术指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Input

输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

Hint

作为splay的终极boss,此题真的是聚集了splay的各种操作啊,简直可怕。

还好,只要掌握了splay的精髓,一样可以解决,此题要注意数组的大小,开50w就好了

一开始开的400w提交竟然说超时。。前后加上点防止越界,询问注意区间就好了。

关于最大连续子序列,只要像线段树那样维护就好了。加上读入挂可以优化1s左右。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int maxn = 1e6;
int n, m, root, a[maxn], l, r, c;
char s[20];

void Scan(int &x)
{
	int flag = 1, res = 0;	char ch;
	while (((ch = getchar()) > '9' || ch < '0') && ch != '-');
	if (ch == '-') flag = -1; else res = ch - '0';
	while ((ch = getchar()) <= '9'&&ch >= '0') res = res * 10 + ch - '0';
	x = flag*res;
}

struct Splays
{
	const static int maxn = 5e5 + 10;			//节点个数
	const static int INF = 0x7FFFFFFF;			//int最大值
	int ch[maxn][2], F[maxn], sz;				//左右儿子,父亲节点和节点总个数
	int C[maxn], S[maxn], A[maxn], G[maxn], L[maxn], R[maxn], M[maxn], K[maxn];
	queue<int> p;
	int Node(int f, int a) { 
		sz = p.front();	p.pop();
		L[sz] = R[sz] = S[sz] = A[sz] = a; C[sz] = 1; K[sz] = G[sz] = ch[sz][0] = ch[sz][1] = 0; F[sz] = f;
		return sz; 
	}//申请一个新节点
	void clear()
	{ 
		while (!p.empty()) p.pop();
		for (int i = 1; i < maxn; i++) p.push(i);
		ch[0][0] = ch[0][1] = F[0] = 0;
		G[0] = K[0] = S[0] = C[0] = 0;
		L[0] = R[0] = M[0] = -INF; 
	}//清空操作
	void pushdown(int x)
	{
		if (G[x])
		{
			G[ch[x][0]] ^= 1;	swap(L[ch[x][0]], R[ch[x][0]]);
			G[ch[x][1]] ^= 1;	swap(L[ch[x][1]], R[ch[x][1]]);
			G[x] ^= 1; swap(ch[x][0], ch[x][1]);
		}
		if (K[x])
		{
			K[ch[x][0]] = K[ch[x][1]] = K[x];
			if (ch[x][0])
			{
				A[ch[x][0]] = A[x];
				S[ch[x][0]] = A[x] * C[ch[x][0]];
				L[ch[x][0]] = R[ch[x][0]] = M[ch[x][0]] = A[x] > 0 ? S[ch[x][0]] : A[x];
			}
			if (ch[x][1])
			{
				A[ch[x][1]] = A[x];
				S[ch[x][1]] = A[x] * C[ch[x][1]];
				L[ch[x][1]] = R[ch[x][1]] = M[ch[x][1]] = A[x] > 0 ? S[ch[x][1]] : A[x];
			}
			K[x] = 0;
		}
	}
	void Count(int x)
	{
		L[x] = max(L[ch[x][0]], S[ch[x][0]] + A[x] + max(0, L[ch[x][1]]));
		R[x] = max(R[ch[x][1]], S[ch[x][1]] + A[x] + max(0, R[ch[x][0]]));
		M[x] = max(0, R[ch[x][0]]) + A[x] + max(0, L[ch[x][1]]);
		M[x] = max(M[x], max(M[ch[x][0]], M[ch[x][1]]));
		C[x] = C[ch[x][0]] + C[ch[x][1]] + 1;
		S[x] = S[ch[x][0]] + S[ch[x][1]] + A[x];
	}
	void rotate(int x, int k)
	{
		int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
		if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
		F[x] = F[y];    F[y] = x;	ch[x][k] = y;
		L[x] = L[y];	R[x] = R[y];	M[x] = M[y]; 
		C[x] = C[y];	S[x] = S[y];    Count(y);
	}
	void Splay(int x, int r)
	{
		for (int fa = F[r]; F[x] != fa;)
		{
			if (F[F[x]] == fa) { rotate(x, x == ch[F[x]][0]); return; }
			int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
			y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
		}
	}
	void build(int fa, int&x, int l, int r)
	{
		if (l > r) return;
		int mid = l + r >> 1;
		x = Node(fa, a[mid]);
		build(x, ch[x][0], l, mid - 1);
		build(x, ch[x][1], mid + 1, r);
		Count(x);
	}
	void find(int &x, int k)
	{
		for (int i = x; i;)
		{
			pushdown(i);
			if (k < C[ch[i][0]]) { i = ch[i][0]; continue; }
			if (k == C[ch[i][0]]) { Splay(i, x); x = i; break; }
			k -= C[ch[i][0]] + 1;	i = ch[i][1];
		}
	}
	void Insert(int &x)
	{
		Scan(l); Scan(r);
		for (int i = 1; i <= r; i++) Scan(a[i]);
		int root;	build(0, root, 1, r);
		find(x, l);	find(ch[x][1], 0);
		ch[ch[x][1]][0] = root;	F[root] = ch[x][1];
		Count(ch[x][1]);	Count(x);
	}
	void earse(int x)
	{
		if (!x) return;
		p.push(x);
		earse(ch[x][0]);
		earse(ch[x][1]);
	}
	void Delete(int &x)
	{
		Scan(l); Scan(r); l--;
		find(x, l);	find(ch[x][1], r);
		earse(ch[ch[x][1]][0]);
		ch[ch[x][1]][0] = 0;
		Count(ch[x][1]);	Count(x);
	}
	void MakeSa(int &x)
	{
		Scan(l); Scan(r); Scan(c); l--;
		find(x, l);	find(ch[x][1], r);
		int g = ch[ch[x][1]][0];
		A[g] = c; S[g] = c*C[g]; K[g] = 1;
		L[g] = R[g] = M[g] = c > 0 ? S[g] : c;
		Count(ch[x][1]);	Count(x);
	}
	void Rotate(int &x)
	{
		Scan(l); Scan(r);	l--;
		find(x, l);	find(ch[x][1], r);
		int g = ch[ch[x][1]][0]; G[g] ^= 1;
		swap(L[g], R[g]);	
		Count(ch[x][1]);	Count(x);
	}
	void GetSum(int &x)
	{
		Scan(l); Scan(r);	l--;
		find(x, l);	find(ch[x][1], r);
		printf("%d\n", S[ch[ch[x][1]][0]]);
	}
	void MaxSum(int &x)
	{
		find(x, 0);	find(ch[x][1], maxn - 3 - p.size());
		printf("%d\n", M[ch[ch[x][1]][0]]);
	}
}solve;


int main()
{
	while (scanf("%d%d", &n, &m) != EOF)
	{
		a[0] = a[n + 1] = root = 0;
		solve.clear();
		for (int i = 1; i <= n; i++) Scan(a[i]);
		solve.build(0, root, 0, n + 1);
		while (m--)
		{
			scanf("%s", s);
			if (s[2] == 'S') solve.Insert(root);
			if (s[2] == 'L') solve.Delete(root);
			if (s[2] == 'K') solve.MakeSa(root);
			if (s[2] == 'V') solve.Rotate(root);
			if (s[2] == 'T') solve.GetSum(root);
			if (s[2] == 'X') solve.MaxSum(root);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值