POJ 3580——SuperMemo(Splay树,经典题)

本文介绍了一款名为SuperMemo的记忆力挑战游戏中的算法实现。针对序列进行多种操作,包括增加值、翻转、旋转等,并通过特殊的树状数据结构来高效处理这些操作,特别是查询子序列最小值的问题。

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

SuperMemo
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 9921 Accepted: 3201
Case Time Limit: 2000MS

Description

Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1A2, ...An}. Then the host performs a series of operations and queries on the sequence which consists:

  1. ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
  2. REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
  3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
  4. INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
  5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
  6. MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2

To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.

Input

The first line contains (≤ 100000).

The following n lines describe the sequence.

Then follows M (≤ 100000), the numbers of operations and queries.

The following M lines describe the operations and queries.

Output

For each "MIN" query, output the correct answer.

Sample Input

5
1 
2 
3 
4 
5
2
ADD 2 4 1
MIN 4 5

Sample Output

5

—————————————————————分割线——————————————


题目大意:

对一个序列进行7种操作:

区间操作:
(1):ADD x y D                对一段区间都增加一个值value
(2):REVERSE x y         翻转一个区间
(3):REVOLVE x y T      对一个区间向右移动T步(转化成交换两个相邻的区间)
(4):INSERT x P            插入一段区间
(5):DELETE x               删除一段区间
(6):MIN x y                     返回一段区间的最小值

思路:

对于右移操作就是讲一段区间分割成两半,然后再合并

[x,a][a+1,y],先将a-1旋转到根,再将a+1旋转到根的右儿子,然后把右儿子的左子树割下来,再将y旋转到根,y+1旋转到根的右儿子,最后将被割下来的子树链接到y+1


注意点:

maxn定义成100001会TL!!!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define Key_value ch[ch[root][1]][0]
#define REP(i,n) for(int i=0;i<(n);++i)
const int INF=1<<30;
const int maxn=100010;
using namespace std;

int root,tot1,ch[maxn][2],key[maxn],Min[maxn],pre[maxn];
int s[maxn],tot2;
int rev[maxn],add[maxn],size[maxn];
int a[maxn];
int n,q;

void update_rev(int rt){
    if(!rt) return ;
    swap(ch[rt][0],ch[rt][1]);
    rev[rt]^=1;
}
void update_add(int rt,int d){
    if(!rt) return ;
    key[rt]+=d;
    add[rt]+=d;
    Min[rt]+=d;
}
void push_up(int rt)
{
    int lson=ch[rt][0],rson=ch[rt][1];
    size[rt]=size[lson]+size[rson]+1;
    Min[rt]=min(key[rt],min(Min[lson],Min[rson]));
}
void push_down(int rt)
{
    int lson=ch[rt][0],rson=ch[rt][1];
    if(add[rt]) {
        update_add(lson,add[rt]);
        update_add(rson,add[rt]);
        add[rt]=0;
    }
    if(rev[rt]) {
        update_rev(lson);
        update_rev(rson);
        rev[rt]=0;
    }
}
void NewNode(int &rt,int f,int k){
    if(tot2) rt=s[tot2--];
    else rt=++tot1;
    ch[rt][0]=ch[rt][1]=0;
    pre[rt]=f;
    key[rt]=k;
    size[rt]=1;
    add[rt]=rev[rt]=0;
    Min[rt]=k;
}
void build(int &rt,int l,int r,int f)
{
    if(l>r) return ;
    int mid=(l+r)>>1;
    NewNode(rt,f,a[mid]);
    build(ch[rt][0],l,mid-1,rt);
    build(ch[rt][1],mid+1,r,rt);
    push_up(rt);
}
void Init()
{
    root=tot1=tot2=0;
    rev[root]=add[root]=ch[root][0]=ch[root][1]=pre[root]=size[root]=0;
    Min[root]=INF;
    NewNode(root,0,-1);
    NewNode(ch[root][1],root,-1);
    REP(i,n) scanf("%d",&a[i]);
    build(Key_value,0,n-1,ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
}
void Rotate(int x,int kind)
{
    int y=pre[x];
    push_down(y);
    push_down(x);
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(pre[y])
        ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    pre[y]=x;
    ch[x][kind]=y;
    push_up(y);
}
void Splay(int x,int goal)
{
    push_down(x);
    while(pre[x]!=goal) {
        if(pre[pre[x]]==goal) {
            Rotate(x,ch[pre[x]][0]==x);
        } else {
            int y=pre[x];
            int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x) {
                Rotate(x,!kind);
                Rotate(x,kind);
            } else {
                Rotate(y,kind);
                Rotate(x,kind);
            }
        }
    }
    push_up(x);
    if(goal==0) root=x;
}

int Get_kth(int rt,int k)
{
    push_down(rt);
    int z=size[ch[rt][0]]+1;
    if(z==k) return rt;
    if(z>k) return Get_kth(ch[rt][0],k);
    else return Get_kth(ch[rt][1],k-z);
}

void Add(int x,int y,int d)
{
    Splay(Get_kth(root,x),0);
    Splay(Get_kth(root,y+2),root);
    update_add(Key_value,d);
    push_up(ch[root][1]);
    push_up(root);
}
void Reverse(int x,int y)
{
    Splay(Get_kth(root,x),0);
    Splay(Get_kth(root,y+2),root);
    update_rev(Key_value);

}
void Revolve(int x,int y,int k)
{
    if(!k) return ;
    int l=y-x+1;
    l=y-(k%l+l)%l;
    Splay(Get_kth(root,x),0);
    Splay(Get_kth(root,l+2),root);
    int tmp=Key_value;
    Key_value=0;
//    pre[Key_value]=0;
    push_up(ch[root][1]);
    push_up(root);
    Splay(Get_kth(root,y-l+x),0);
    Splay(Get_kth(root,y-l+x+1),root);
    Key_value=tmp;
    pre[Key_value]=ch[root][1];
    push_up(ch[root][1]);
    push_up(root);
}
void Insert(int x,int v)
{
    Splay(Get_kth(root,x+1),0);
    Splay(Get_kth(root,x+2),root);
    NewNode(Key_value,ch[root][1],v);
    push_up(ch[root][1]);
    push_up(root);
}
void erase(int rt)
{
    if(!rt) return ;
    s[++tot2]=rt;
    erase(ch[rt][0]);
    erase(ch[rt][1]);
}
void Delete(int x)
{
    Splay(Get_kth(root,x),0);
    Splay(Get_kth(root,x+2),root);
    erase(Key_value);
    pre[Key_value]=0;
    Key_value=0;
    push_up(ch[root][1]);
    push_up(root);
}
int Get_answer(int x,int y)
{
    Splay(Get_kth(root,x),0);
    Splay(Get_kth(root,y+2),root);
    return Min[Key_value];
}
int main(){
    while(scanf("%d",&n)!=EOF){
        Init();
		scanf("%d",&q);

		char str[10];
		int l,r,k;
		while(q--){
			scanf("%s",str);
			if(!strcmp(str,"ADD")){
				scanf("%d%d%d",&l,&r,&k);
				Add(l,r,k);
			}
			else if(!strcmp(str,"REVERSE")){
				scanf("%d%d",&l,&r);
				Reverse(l,r);
			}
			else if(!strcmp(str,"REVOLVE")){
				scanf("%d%d%d",&l,&r,&k);
				Revolve(l,r,k);
			}
			else if(!strcmp(str,"INSERT")){
				scanf("%d%d",&l,&k);
				Insert(l,k);
			}
			else if(!strcmp(str,"DELETE")){
				scanf("%d",&l);
				Delete(l);
			}
			else{
				scanf("%d%d",&l,&r);
				printf("%d\n",Get_answer(l,r));
			}
		}
	}
	return 0;
}



智能网联汽车的安全员高级考试涉及多个方面的专业知识,包括但不限于自动驾驶技术原理、车辆传感器融合、网络安全防护以及法律法规等内容。以下是针对该主的一些核心知识点解析: ### 关于智能网联车安全员高级考试的核心内容 #### 1. 自动驾驶分级标准 国际自动机工程师学会(SAE International)定义了六个级别的自动驾驶等级,从L0到L5[^1]。其中,L3及以上级别需要安全员具备更高的应急处理能力。 #### 2. 车辆感知系统的组成与功能 智能网联车通常配备多种传感器,如激光雷达、毫米波雷达、摄像头和超声波传感器等。这些设备协同工作以实现环境感知、障碍物检测等功能[^2]。 #### 3. 数据通信与网络安全 智能网联车依赖V2X(Vehicle-to-Everything)技术进行数据交换,在此过程中需防范潜在的网络攻击风险,例如中间人攻击或恶意软件入侵[^3]。 #### 4. 法律法规要求 不同国家和地区对于无人驾驶测试及运营有着严格的规定,考生应熟悉当地交通法典中有关自动化驾驶部分的具体条款[^4]。 ```python # 示例代码:模拟简单决策逻辑 def decide_action(sensor_data): if sensor_data['obstacle'] and not sensor_data['emergency']: return 'slow_down' elif sensor_data['pedestrian_crossing']: return 'stop_and_yield' else: return 'continue_driving' example_input = {'obstacle': True, 'emergency': False, 'pedestrian_crossing': False} action = decide_action(example_input) print(f"Action to take: {action}") ``` 需要注意的是,“橙点同学”作为特定平台上的学习资源名称,并不提供官方认证的标准答案集;建议通过正规渠道获取教材并参加培训课程来准备此类资格认证考试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值