zoukankan      html  css  js  c++  java
  • bzoj4137&&dtoj#2259. 火星商店问题

    题目描述:

    火星上的一条商业街里按照商店的编号$1,2,3,…,n$,依次排列着$n$个商店。商店里出售的琳琅满目的商品中,每种商品都用一个非负整数$val$来标价。每个商店每天都有可能进一些新商品,其标价可能与已有商品相同。

    火星人在这条商业街购物时,通常会逛这条商业街某一段路上的所有商店,譬如说商店编号在区间$[L,R]$中的商店,从中挑选$1$件自己最喜欢的商品。每个火星人对商品的喜好标准各不相同。通常每个火星人都有一个自己的喜好密码$x$。对每种标价为$val$的商品,喜好密码为$x$的火星人对这种商品的喜好程度与$val$异或$x$的值成正比。也就是说,$valspace xorspace x$的值越大,他就越喜欢该商品。每个火星人的购物卡在所有商店中只能购买最近$d$天内(含当天)进货的商品。另外,每个商店都有一种特殊商品不受进货日期限制,每位火星人在任何时刻都可以选择该特殊商品。每个商店中每种商品都能保证供应,不存在商品缺货的问题。

    对于给定的按时间顺序排列的事件,计算每个购物的火星人的在本次购物活动中最喜欢的商品,即输出$valspace xorspace x$的最大值。这里所说的按时间顺序排列的事件是指以下$2$种事件:

    事件$0$,用三个整数$0,s,v$,表示编号为$s$的商店在当日新进一种标价为$v$的商品。

    事件$1$,用$5$个整数$1,L,R,x,d$,表示一位火星人当日在编号为$L$到$R$的商店购买$d$天内的商品,该火星人的喜好密码为$x$。

    (补充说明:每个事件$0$代表新一天的开始。每个事件$1$和其之前的最后一个事件$0$同一天,如果没有当做第$0$天。第一个事件$0$代表第$1$天的开始。)

    数据范围:

    对于数据点 $ 1 $,$ n,m leq 1000 $。
    对于数据点 $ 2 , 3$,$ d = 0 $。
    对于数据点 $ 4 , 5 , 6 $,$ d = $进货次数。
    对于数据点 $ 7 $,$ n = m = 20000 $。
    对于数据点 $ 8 $,$ n = m = 50000 $。
    对于所有数据点,$ 1leq n,m,x,valleq 100000$。

    算法标签:可持久化trie树,线段树分治

    思路:

    对于时间没有要求的点,可以先单独拿出来,建成一棵可持久化线段树,先统计答案。

    之后把每一个商品挂在线段树上,之后在线段树上依此递归,每一层只对在当前这层区间的商品在可持久化线段树上更新,并对答案进行更新。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e5+5;
    int n,m,son[N*20][2],cnt=1,sz[N*20],tot,nt,ans[N],st,top,dy[N],rt[N];
    vector<int> v[N<<2];
    struct node{
        int s,v,d;
    }t[N],tmp1[N],tmp2[N];
    struct data{
        int l,r,ql,qr,v;
    }s[N];
    bool cmp(node t1,node t2){
        return t1.s<t2.s;
    }
    il int read(){
        int x,f=1;char ch;
        _(!)ch=='-'?f=-1:f;x=ch^48;
        _()x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    il void ins(int &x,int y,int v){
        x=++tot;
        int xx=x;
        for(int i=17;i>=0;i--){
            int o=(v>>i)&1;
            son[xx][o]=++tot;son[xx][o^1]=son[y][o^1];
            xx=son[xx][o];y=son[y][o];
            sz[xx]=sz[y]+1;
        }
    }
    il void insert(int x,int l,int r,int ql,int qr,int val){
        if(ql<=l&&r<=qr){
            v[x].push_back(val);return;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)insert(x<<1,l,mid,ql,qr,val);
        if(mid<qr)insert(x<<1|1,mid+1,r,ql,qr,val);
    }
    il int query(int x,int y,int v){
        int ret=0;
        for(int i=17;i>=0;i--){
            int o=(v>>i)&1;
            if(sz[son[x][o^1]]^sz[son[y][o^1]])ret|=(1<<i),x=son[x][o^1],y=son[y][o^1];
            else x=son[x][o],y=son[y][o];
        }
        return ret;
    }
    il void work(int x,int l,int r){
        tot=0;top=0;
        for(int i=l;i<=r;i++){
            int s=t[i].s;
            dy[++top]=s;
            ins(rt[top],rt[top-1],t[i].v);
        }
        for(int i=0;i<v[x].size();i++){
            int now=v[x][i];
            int ql=lower_bound(dy+1,dy+1+top,s[now].l)-dy-1;
            int qr=upper_bound(dy+1,dy+1+top,s[now].r)-dy-1;
            ans[now]=max(ans[now],query(rt[ql],rt[qr],s[now].v));
        }
    }
    il void solve(int x,int l,int r,int ql,int qr){
        work(x,ql,qr);
        if(l==r)return;int mid=(l+r)>>1;
        int a=0,b=0;
        for(int i=ql;i<=qr;i++){
            if(t[i].d<=mid)tmp1[++a]=t[i];
            else tmp2[++b]=t[i];
        }
        for(int i=ql;i<=ql+a-1;i++)t[i]=tmp1[i-ql+1];
        for(int i=ql+a;i<=qr;i++)t[i]=tmp2[i-ql-a+1];
        solve(x<<1,l,mid,ql,ql+a-1);solve(x<<1|1,mid+1,r,ql+a,qr);
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)ins(rt[i],rt[i-1],read());
        for(int i=1;i<=m;i++){
            int op=read();
            if(!op){
                int s=read(),v=read();
                t[++cnt]=(node){s,v,cnt};
            }
            else{
                int l=read(),r=read(),x=read(),d=read();
                ans[++st]=query(rt[l-1],rt[r],x);
                s[st]=(data){l,r,max(1,cnt-d+1),cnt,x};
            }
        }
        for(int i=1;i<=st;i++)insert(1,1,cnt,s[i].ql,s[i].qr,i);
        sort(t+1,t+1+cnt,cmp);
        solve(1,1,cnt,1,cnt);
        for(int i=1;i<=st;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    mysqldump 导出数据库为DBname的表名为Tname的表结构 导出数据库的所有表的表结构
    mysqldump 备份某张表 Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions,
    nfs missing codepage or helper program, or other error
    date 增加一个小时 减少一个小时
    mysqldump 备份单个数据库
    mysql删除账户
    怎么删除某个用户的所有帖子?
    mongodb删除重复数据
    ReSharper2018破解详细方法
    激活windows和office
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10434990.html
Copyright © 2011-2022 走看看