FOJ 1962 新击鼓传花游戏 线段树

维护一个sum数组,有点划分树的思想,写过划分树的应该能看出来

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
const int maxn=500005;
int sum[maxn<<2],is[maxn];
void pushup(int rt)
{
    sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void build(int rt,int l,int r)
{
     if(l==r)
     {
         is[l]=sum[rt]=1;
         return;
     }
     int m=(l+r)>>1;
     build(rt*2,l,m);
     build(rt*2+1,m+1,r);
     pushup(rt);
}
void change(int rt,int l,int r,int pos,int c)
{
    if(l==r)
    {
        sum[rt]=c;
        return;
    }
    int m=(l+r)>>1;
    if(pos<=m)change(rt*2,l,m,pos,c);
    else change(rt*2+1,m+1,r,pos,c);
    pushup(rt);
}
int query(int rt,int l,int r,int k)
{
    if(l==r)
    {
        return l;
    }
    int m=(l+r)>>1;
    if(sum[rt*2]>=k)return query(rt*2,l,m,k);
    else return query(rt*2+1,m+1,r,k-sum[rt*2]);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=0;i<m;++i)
    {
        char s[5];
        int k;
        scanf("%s%d",s,&k);
        if(s[0]==‘L‘)
        {
            int x=query(1,1,n,k);
            is[x]=0;
            change(1,1,n,x,0);
        }
        else if(s[0]==‘R‘)
        {
            if(is[k]==1)continue;
            is[k]=1;
            change(1,1,n,k,1);
        }
        else
        {
            int x=query(1,1,n,k);
            printf("%d\n",x);
        }
    }
    return 0;
}

时间: 2024-07-29 07:31:16

FOJ 1962 新击鼓传花游戏 线段树的相关文章

猿辅导:击鼓传花(动态规划)

题目描述 学校联欢晚会的时候,为了使每一个同学都能参与进来,主持人常常会带着同学们玩击鼓传花的游戏.游戏规则是这样的:n个同学坐着围成一个圆圈,指定一个同学手里拿着一束花,主持人在旁边背对着大家开始击鼓,鼓声开始之后拿着花的同学开始传花,每个同学都可以把花传给自己左右的两个同学中的一个(左右任意),当主持人停止击鼓时,传花停止,此时,正拿着花没传出去的那个同学就要给大家表演一个节目. 聪明的小赛提出一个有趣的问题:有多少种不同的方法可以使得从小赛手里开始传的花,传了m次以后,又回到小赛手里.对于

洛谷1558 色板游戏 线段树

我先立个Flag 我,这几天,要过1W道线段树题. 题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L.现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. "C A B C" 指在A到 B 号方格中涂上颜色 C.2. "P A B" 指老师的提问:A到 B号方格中有几种颜色.学校的颜料盒中一共有 T 种颜料.为简便起见,我

51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线

 区间计数 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{Ai,Ai+1,...,Aj}=max{Bi,Bi+1,...,Bj}] 注:[ ]内表达式为真,则为1,否则为0. 1≤N≤3.5×1051≤Ai,Bi≤N 样例解释: 7个区间分别为:(1,4),(1,5),(2,4),(2,5),(3,3),(3,5),(4,5) Input 第一行一个整数N 第二行

P1558 色板游戏 线段树(区间修改,区间查询)

题意: 给n,m,k,n长度,k个操作,m种颜色 操作C:输入A,B,C,区间[A,B]变成C颜色,可能A>B,所以要确保A<B 操作P:输入A,B,区间[A,B]的颜色种类 思路: 因为颜色只有30种,可以用位运算,然后进行lazy标记 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define il inline 5 #define it register int 6 #de

[P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)

题意:有 n个房间,题目给出两个操作,若 op==1,就输出最靠左的连续空房数量为 x的房间序列的最左边的序号,然后将这些房间改为入住:若 op==2,就将从 x~y的的序列全部改为空房: 解法:线段树+懒标记下传: 1.线段树:题目让在一个很长的序列操作很多次,暴力显然过不了,要用线段树优化: 2.懒标记下传:这是本题的精髓.   此题要维护的不是序列上的数值总和,而是该序列的最长连续空房的长度 sum,从该节点从左向右数最长的连续空房长度 lm,以及从该节点从右向左数最长的连续空房长度 rm

【bzoj3196】 Tyvj 1730 二逼平衡树 线段树套Treap

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) 输入 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数,表示有序序列下面有m行,opt表示操作标号若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名若opt=2 则为操

hdu4614Vases and Flowers 线段树

//给一个数组,两个操作 //1 A F 以A为起点的F个空闲空间插花,输出起点和终点 //2 L R 将[L , R]的所有的有花的花拔除,问清除了几朵花 //用线段树维护剩余空间的个数 //然后再在查询时找出空间 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 50010 ; #define left v<<1 #de

线段树 FOJ 2174

FOJ  2174 区间跟新,区间询问: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define lson l,mid,rt<<1 5 #define rson mid+1,r,rt<<1|1 6 7 using namespace std; 8 typedef long long LL; 9 const int N=110001; 10 int sum[N

【BZOJ-2892&amp;1171】强袭作战&amp;大sz的游戏 权值线段树+单调队列+标记永久化+DP

2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] Description 在一个没有冬马的世界里,经历了学园祭后的春希着急着想要见到心爱的雪菜.然而在排队想见雪菜的fans太多了,春希一时半会凑不到雪菜面前. 作为高帅富,这样的问题怎么能难倒春希?春希从武也手中拿到了取自金闪闪宝库里的多啦A梦的传话筒,并且给每一个排队的fans都发了一个传话筒. 于