UOJ 218 火车管理

http://uoj.ac/problem/218

思路:建立一个可持久化线段树,代表这个位置的火车是哪辆,然后再弄一个线段树维护答案。

如果询问,直接询问线段树。

如果区间压入,直接在主席树上面压入,然后更新线段树答案

如果弹出,那么直接找主席树当前位之前的火车是那辆,然后修改线段树答案,再修改当前主席树答案。

改题的时候蜜汁错误。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
int tr[40000005],ls[40000005],tag[40000005],rs[40000005];
int tg[2000005],sum[2000005],sz,rt[500005],a[500005];
int n,m,ty;
int read(){
    int t=0,f=1;char ch=getchar();
    while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
    while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
    return t*f;
}
void pushdown(int k){
    if (tag[k]==-1) return;
    if (!ls[k]) ls[k]=++sz;
    if (!rs[k]) rs[k]=++sz;
    tag[ls[k]]=tag[rs[k]]=tr[ls[k]]=tr[rs[k]]=tag[k];
    tag[k]=-1;
}
void add(int &k,int kk,int l,int r,int x,int y,int v){
    k=++sz;tag[k]=-1;
    if (x==l&&r==y){
        tag[k]=tr[k]=v;
        return;
    }
    pushdown(kk);
    int mid=(l+r)>>1;
    ls[k]=ls[kk];rs[k]=rs[kk];
    if (y<=mid) add(ls[k],ls[kk],l,mid,x,y,v);
    else
    if (x>mid) add(rs[k],rs[kk],mid+1,r,x,y,v);
    else
    add(ls[k],ls[kk],l,mid,x,mid,v),add(rs[k],rs[kk],mid+1,r,mid+1,y,v);
}
int query(int k,int l,int r,int pos){
    if (!k||l==r) return tr[k];
    pushdown(k);
    int mid=(l+r)>>1;
    if (pos<=mid) return query(ls[k],l,mid,pos);
    else return query(rs[k],mid+1,r,pos);
}
void pushdown(int k,int l,int r){
    if (tg[k]==-1||l==r) return;
    tg[k*2]=tg[k*2+1]=tg[k];
    int mid=(l+r)>>1;
    sum[k*2]=tg[k]*(mid-l+1);
    sum[k*2+1]=tg[k]*(r-mid);
    tg[k]=-1;
}
void modify(int k,int l,int r,int x,int y,int v){
    pushdown(k,l,r);
    if (x==l&&r==y){
        tg[k]=v;sum[k]=(r-l+1)*v;
        pushdown(k,l,r);
        return;
    }
    int mid=(l+r)>>1;
    if (y<=mid) modify(k*2,l,mid,x,y,v);
    else
    if (x>mid) modify(k*2+1,mid+1,r,x,y,v);
    else modify(k*2,l,mid,x,mid,v),modify(k*2+1,mid+1,r,mid+1,y,v);
    sum[k]=sum[k*2]+sum[k*2+1];
}
int getsum(int k,int l,int r,int x,int y){
    pushdown(k,l,r);
    if (x==l&&r==y){
        return sum[k];
    }
    int mid=(l+r)>>1,z=0;
    if (y<=mid) return getsum(k*2,l,mid,x,y);
    else
    if (x>mid) return getsum(k*2+1,mid+1,r,x,y);
    else return getsum(k*2,l,mid,x,mid)+getsum(k*2+1,mid+1,r,mid+1,y);
}
int main(){
    n=read();m=read();ty=read();
    int ans=0;
    for (int i=1;i<=m;i++){
        rt[i]=rt[i-1];
        int opt=read(),l=read();l=(l+ty*ans)%n+1;
        if (opt==2){
            int x=query(rt[i],1,n,l);
            if (x){
                int y=query(rt[x-1],1,n,l);
                add(rt[i],rt[i],1,n,l,l,y);
                modify(1,1,n,l,l,a[y]);
            }
            continue;
        }
        int r=read();r=(r+ty*ans)%n+1;
        if (l>r) std::swap(l,r);
        if (opt==1){printf("%d\n",ans=getsum(1,1,n,l,r));}
        else{
           a[i]=read();
           add(rt[i],rt[i],1,n,l,r,i);
           modify(1,1,n,l,r,a[i]);
        }
    }
    return 0;
}
时间: 2025-01-03 08:25:31

UOJ 218 火车管理的相关文章

UOJ #218. 【UNR #1】火车管理

http://uoj.ac/problem/218 维护一颗主席树 查询入栈相当于区间修改,弹栈相当于返回历史版本 维护区间求和 原文地址:https://www.cnblogs.com/sssy/p/8322124.html

UOJ#218. 【UNR #1】火车管理 线段树 主席树

原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和的线段树上完成这个问题. 于是本题的重点转到了如何求新的栈顶. 考虑用一个主席树维护一下每一个时刻每一个位置的栈顶元素的进栈时间,那么新的栈顶就是 当前位置栈顶的进栈时间-1 这时候的栈顶元素,然后这个东西也可以用我们维护的进栈时间来得到,所以我们只需要弄一个支持区间覆盖单点查询历史版本的主席树:这

东北育才10天大总结

老师们 Scanf的嗓门照例是最大的.恩. “我是山里的孩子……小的时候背书,整个山头都听得见……” 有一个哈师大附中的竞赛教练很……怎么说呢?接地气好了. Scanf说东北人很耿直,似乎确实是这样的.衡水的教练早就被遣返了…… “他啊,监考去了!” 虽然他不在,但还是不还手机.让衡水的人天天在电脑上颓废…… Scanf不在,你看我们就很老实.他到处“乱”玩,甚至跑到了国境线边,连火车票都忘了买,坐高铁去,乘绿皮火车回,路过长白山就去玩了一趟,结果暴风雪逼得他去吃“暴辣”的烤鱿鱼. “我看<三八

UNR #1 题解

虽然题解讲的很清楚...但还是再写一遍骗一点访问量QAQ A. 争夺圣杯 还是想说一下,这题是原题啊...想做的人可以戳codechef上的MTMXSUM(懒得贴链接了,套了个壳,不过正常人应该都能看得出来) 显然异或输出没什么奇怪的性质... 考虑一个元素a[x]在哪些区间中会成为最大值,我们可以用单调栈找出前面比这个元素大的第一个元素a[l],右边大的第一个元素a[r]. 考虑这个元素对每一长度的贡献,设p=x-l,q=r-x,那么对于区间[s,t],只有当l<s<=x,x<=t&l

[UOJ#128][BZOJ4196][Noi2015]软件包管理器

试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.不可避免地,你要解决软件包之间的依赖问题.如果软件包A依赖软件包B,那

UOJ UR#9 App管理器

题目传送门 题目大意大概就是给你一个混合图(既有有向边又有无向边),对于每条无向边,u-v,问删去u->v,或删去v->u那条可以使新图强连通.(保证数据有解). 这道题前几个数据点送分. 枚举每一条边,先将它去掉,遍历图,如果可以达到所有点,即强连通. 比如去掉u->v,其实只要dfs(u),判断是否能到达v即可.可以直接删去,否则删另一条边,删去后因为图强连通,所以对之后的操作无影响. code: #include <cstdio> #include <cstrin

【Sprint3冲刺之前】日历表的事件处理和管理(刘铸辉)

我的Sprint2冲刺--日历表的事件处理和管理(刘铸辉,刘静) 我的Sprint2冲刺计划领到的任务是和静姐结对编程,完成日历表的事件处理和管理,下面详细讲解下技术细节. 1.设计结构图 首先要画出整个UI设计图,方便理解这个日历布局和日历样式的绘制. 这里总共分解为两个 View 文件: 1:calender_main.xml(Calender.java用来绘制日历表和日历表中的事件) 作为启动的主画面,新建项目时,首先生成. schedule_toptext:用来显示年月日,闰几月,年份和

终于懂了:FWinControls子控件的显示是由Windows来管理,而不是由Delphi来管理

在研究TCustomControl的显示过程中,怎么样都找不到刷新FWinControls并重新显示的代码: procedure TWinControl.PaintHandler(var Message: TWMPaint); var I, Clip, SaveIndex: Integer; DC: HDC; PS: TPaintStruct; begin DC := Message.DC; if DC = 0 then DC := BeginPaint(Handle, PS); try if

ios开发-UI基础-应用管理(单纯界面)

功能分析 以九宫格的形式展示应用信息 点击下载按钮后,做出相应操作(弹出一个提示"正在下载",相应应用的下载按钮变为"已下载") 步骤分析 搭建UI界面 加载应用信息 根据应用的个数创建对应的view 监听下载按钮的点击 应用截图: 这个小的综合实例涉及到的知识点: UIView的常见属性和方法 九宫格的计算方法 字典转模型 xib的使用 view的封装 简单的MVC 九宫格分析: 搭建九宫格的步骤 明确每一块用的是什么view 明确每个view之间的父子关系 先尝