luogu P4585 [FJOI2015]火星商店问题

luogu

异或最大值显然可以01trie贪心选取

然后涉及到时间区间内元素贡献,可以把trie可持久化

还涉及区间内集合贡献,那么我们搞个线段树,把操作放到对应节点到根的链上,把询问放到对应区间的log个节点上,然后对着每个线段树节点计算贡献,算完后清空trie,空间\(O(nlogn)\),时间两个\(log\)

还有些和时间无关的物品,单独处理即可

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double

using namespace std;
const int N=1e5+10;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int n,m,q,an[N];
int s[N*70],ch[N*70][2],rt[N],tt;
void inst(int o1,int o2,int x)
{
    s[o1]=s[o2]+1;
    for(int i=16;~i;--i)
    {
        int xx=x>>i&1;
        ch[o1][xx]=++tt,ch[o1][xx^1]=ch[o2][xx^1];
        o1=ch[o1][xx],o2=ch[o2][xx];
        s[o1]=s[o2]+1;
    }
}
int quer(int o1,int o2,int x)
{
    int an=0;
    for(int i=16;~i;--i)
    {
        int xx=(x>>i&1)^1;
        if(s[ch[o1][xx]]-s[ch[o2][xx]]) an|=1<<i,o1=ch[o1][xx],o2=ch[o2][xx];
        else o1=ch[o1][xx^1],o2=ch[o2][xx^1];
    }
    return an;
}
struct node
{
    int o,d,x;
};
vector<node> op[N<<2],op2[N<<2];
vector<int> px;
void setop(bool oo,int o,int l,int r,int lx,node x)
{
    oo?op[o].push_back(x):op2[o].push_back(x);
    if(l==r) return;
    int mid=(l+r)>>1;
    if(lx<=mid) setop(oo,o<<1,l,mid,lx,x);
    else setop(oo,o<<1|1,mid+1,r,lx,x);
}
void setqr(bool oo,int o,int l,int r,int ll,int rr,node x)
{
    if(ll<=l&&r<=rr){oo?op[o].push_back(x):op2[o].push_back(x);return;}
    int mid=(l+r)>>1;
    if(ll<=mid) setqr(oo,o<<1,l,mid,ll,rr,x);
    if(rr>mid) setqr(oo,o<<1|1,mid+1,r,ll,rr,x);
}
int fdd(int x)
{
    int an=0,l=0,r=px.size()-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(px[mid]<x) an=px[mid],l=mid+1;
        else r=mid-1;
    }
    return an;
}
void wk(int o,int l,int r)
{
    int latt=tt,nn=0;
    vector<node>::iterator it;
    for(it=op[o].begin();it!=op[o].end();++it)
    {
        node nw=*it;
        if(!nw.o)
        {
            px.push_back(nw.d);
            ++nn;
            inst(rt[nw.d]=++tt,nn>=2?rt[px[nn-2]]:0,nw.x);
        }
        else if(nn)
        {
            int o1=px[nn-1],o2=o?fdd(nw.d):0;
            if(o1>o2) an[nw.o]=max(an[nw.o],quer(rt[o1],rt[o2],nw.x));
        }
    }
    vector<int>::iterator i1;
    for(i1=px.begin();i1!=px.end();++i1)
    {
        int xx=*i1;
        rt[xx]=0;
    }
    px.clear();
    while(tt>latt)
    {
        s[tt]=ch[tt][0]=ch[tt][1]=0;
        --tt;
    }
    nn=0;
    for(it=op2[o].begin();it!=op2[o].end();++it)
    {
        node nw=*it;
        if(!nw.o)
        {
            int las=rt[1];
            inst(rt[1]=++tt,las,nw.x);
        }
        else
            an[nw.o]=max(an[nw.o],quer(rt[1],rt[0],nw.x));
    }
    while(tt>latt)
    {
        s[tt]=ch[tt][0]=ch[tt][1]=0;
        --tt;
    }
    if(l<r) wk(o<<1,l,(l+r)>>1),wk(o<<1|1,((l+r)>>1)+1,r);
}

int main()
{
    n=rd(),q=rd();
    for(int i=1;i<=n;++i) setop(0,1,1,n,i,(node){0,i,rd()});
    for(int i=1,j=0;i<=q;++i)
    {
        int ty=rd();
        if(ty==0)
        {
            ++j;
            int x=rd(),y=rd();
            setop(1,1,1,n,x,(node){0,j,y});
        }
        else
        {
            int l=rd(),r=rd(),x=rd(),d=rd();
            setqr(1,1,1,n,l,r,(node){++m,j-d+1,x});
            setqr(0,1,1,n,l,r,(node){m,j-d+1,x});
        }
    }
    wk(1,1,n);
    for(int i=1;i<=m;++i) printf("%d\n",an[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/smyjr/p/11559691.html

时间: 2024-10-09 11:52:26

luogu P4585 [FJOI2015]火星商店问题的相关文章

洛谷 P4585 [FJOI2015]火星商店问题

(勿看,仅作笔记) bzoj权限题... https://www.luogu.org/problemnew/show/P4585 对于特殊商品,直接可持久化trie处理一下即可 剩下的,想了一段时间cdq,但是没想出来...应该是不行的 事实上,如果询问的不是最大值,而是一些满足[l,r]的答案等于[1,r]的答案-[1,l-1]的答案的东西,那么的确可以每个询问拆成两个直接cdq... 但是这题就不能..不过可以线段树分治,这是基于[l,r]的答案可以被分成多个线段树上区间(这些区间的并等于[

[FJOI2015]火星商店问题(分治+可持久化)

题目描述 火星上的一条商业街里按照商店的编号1,2 ,-,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品,其标价可能与已有商品相同. 火星人在这条商业街购物时,通常会逛这条商业街某一段路上的所有商店,譬如说商店编号在区间[L,R]中的商店,从中挑选1件自己最喜欢的商品.每个火星人对商品的喜好标准各不相同.通常每个火星人都有一个自己的喜好密码x.对每种标价为val的商品,喜好密码为x的火星人对这种商品的喜好程度与val

【题解】FJOI2015火星商店问题

好几天之前做的题目了,一直想写一下博客也没腾出时间来,今天赶紧把坑给填上呼呼呼~ 这道题首先如果只考虑每个商店中没有时间限制的物品时,我们只需要使用一棵可持久化trie树来维护区间内的异或最大值即可,这样我们可以把两部分的问题分离开来. 之后我们再考虑有时间限制与编号限制的情况下,该怎样做?无脑做法线段树套trie,直接在对应的区间trie树上贪心,如果该条边的最后更新时间在允许的范围内,说明可以走这条边.虽然这样也可以卡过去(主要在于卡空间),但我们来介绍一种更加妙妙的线段树分治做法.其实我感

bzoj 4137 [FJOI2015]火星商店问题——线段树分治+可持久化01trie树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyLex/p/7281110.html 看了看它的两道例题,就没写. 特殊商品可以直接用可持久化trie做. 其他部分用线段树分治.修改是单点的,询问是区间,原来想的是把询问区间定位后有 mlogn 个,在线段树的每个叶子上贡献一番:结果TLE了,因为若是在叶子处贡献,一个询问就要做 r-l+1 次.

bzoj4137 [FJOI2015]火星商店问题

比较容易想到的做法是线段树套字典树,修改操作时在字典树上经过的节点维护一个最近被访问过的时间,这样询问操作只经过满足时间条件的节点,时间复杂度O(NlogN^2)但是因为线段树每个节点都要套个字典树,这样的话空间是不够的,不过由于可以离线处理,我们可以先把每个修改和询问操作所访问的线段树节点保存下来,然后一个个节点去做,这样的话空间复杂度就可以保证了. 代码 1 #include<cstdio> 2 #include<set> 3 #include<vector> 4

【Luogu】P3356火星探险问题(费用流)

题目链接 网络流一条边都不能多连?没道理呀? 不过单看这题的确是个sb题…… #include<cstdio> #include<algorithm> #include<cstring> #include<cctype> #include<cstdlib> #include<queue> #define maxn 100 #define maxm 100000 #define lim n*m #define F(i,j) ((i-1)

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

线段树分治

2014徐寅展论文<线段树在一类分治问题上的应用>读后感. 线段树分治 线段树分治其实就是有撤销操作的时间分治. 题目让你维护一些信息,每次可以询问,可以执行一种操作,也可以将之前的某个这种操作撤回. 操作容易维护,但撤回操作不容易维护. 需要将操作,询问都离线下来.将时间轴画出来,那么每个操作只在时间轴上的一个区间内生效. 用线段树给这个区间打上这个操作的标记,维护信息. TJOI2018 数学计算 小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型: m: x = x * m

2019-9-11做题记录

1.[luogu4921]情侣,给我烧了: 我们这里只讨论直接算代替容斥的做法. $n$个情侣,恰好有$k$个不和谐,枚举是哪$k$个,$C_n^k$.坐在哪些位置上,$C_n^k$.确定先后关系(为下面算$f$埋下伏笔),$2^n$.确定顺序,$k! (n-k)!$. 剩下还要求$i$对情侣,已经指定了顺序,和彼此先后关系,求任意一对都不坐在一排上的方案数.也就是说对于任意一种方案,我们都可以唯一确定它的顺序和彼此的先后关系,因为我已经乘过了.考虑顺序和彼此先后关系怎么体现:也就是说,对于“$