zoukankan      html  css  js  c++  java
  • Luogu P4585 [FJOI2015]火星商店问题

    题目
    可持久化01Trie+线段树分治。
    首先用Trie算出所有询问对于特殊商品的答案。
    然后我们给每一个进货的商品加上一个时间值,每个询问就会有相对应的时间区间。
    我们开一棵时间的线段树,把每个询问加到线段树上,每个节点用一个vector储存这个节点的询问。
    显然每个询问最多会在(log)个节点上。
    然后我们把所有进货按商店排序,由线段树自顶向下进行分治,分治的时候还记录一下进货的区间。
    每次到线段树的某个节点时,先计算出当前节点的答案(因为所有进货是按商店排序的,所以依旧可以用01Trie算,算之前记得清空),然后把时间小于等于(mid)的放到左边,大于(mid)的放到右边,向下递归。

    #include<bits/stdc++.h>
    #define pb push_back
    #define ls p<<1
    #define rs p<<1|1
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=100007;
    int ch[N<<5][2],sum[N<<5],root[N],ans[N],stk[N],d[18],top,n,m,cnt;
    vector<int>vec[N];
    struct node{int l,r,L,R,x;}q[N];
    struct Node{int s,v,t;}a[N],t1[N],t2[N];
    int operator<(Node a,Node b){return a.s<b.s;}
    int read(){int x=0;char c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
    int max(int a,int b){return a>b? a:b;}
    void split(int x)
    {
        memset(d,0,sizeof d);
        for(int i=0;i<=17;++i) d[i]=x>>i&1;
    }
    void insert(int &p,int pre)
    {
        sum[p=++cnt]=sum[pre]+1;
        for(int i=17,t=p;~i;--i) ch[t][d[i]^1]=ch[pre][d[i]^1],pre=ch[pre][d[i]],sum[t=ch[t][d[i]]=++cnt]=sum[pre]+1;
    }
    int query(int l,int r)
    {
        int ans=0,i;
        for(i=17;~i;--i)
    	if(sum[ch[l][d[i]^1]]^sum[ch[r][d[i]^1]]) ans|=1<<i,l=ch[l][d[i]^1],r=ch[r][d[i]^1];
    	else l=ch[l][d[i]],r=ch[r][d[i]];
        return ans;
    }
    void update(int p,int l,int r,int L,int R,int x)
    {
        if(L>R||r<L||l>R) return ;
        if(L<=l&&r<=R) return (void)(vec[p].pb(x));
        update(ls,l,mid,L,R,x);update(rs,mid+1,r,L,R,x);
    }
    void cal(int p,int L,int R)
    {
        cnt=0;
        int i,l,r,k,top=0;
        for(i=L;i<=R;++i) stk[++top]=a[i].s,split(a[i].v),insert(root[top],root[top-1]);
        for(i=0;i<vec[p].size();++i)
    	k=vec[p][i],l=upper_bound(stk+1,stk+top+1,q[k].l-1)-(stk+1),r=upper_bound(stk+1,stk+top+1,q[k].r)-(stk+1),split(q[k].x),ans[k]=max(ans[k],query(root[l],root[r]));
    }
    void solve(int p,int l,int r,int L,int R)
    {
        if(L>R) return;
        cal(p,L,R);
        if(l==r) return;
        int p1=0,p2=0,i;
        for(i=L;i<=R;++i) if(a[i].t<=mid) t1[++p1]=a[i]; else t2[++p2]=a[i];
        for(i=1;i<=p1;++i) a[i+L-1]=t1[i];
        for(i=1;i<=p2;++i) a[i+L+p1-1]=t2[i];
        solve(ls,l,mid,L,L+p1-1),solve(rs,mid+1,r,L+p1,R);
    }
    int main()
    {
        n=read(),m=read();
        int i,tot=0,T=0,l,r,x,d;
        for(i=1;i<=n;++i) split(read()),insert(root[i],root[i-1]);
        while(m--)
    	if(read()) l=read(),r=read(),x=read(),d=read(),split(x),ans[++tot]=query(root[l-1],root[r]),q[tot]=(node){l,r,max(1,T-d+1),T,x};
    	else x=read(),d=read(),a[++T]=(Node){x,d,T};
        for(i=1;i<=tot;++i) update(1,1,T,q[i].L,q[i].R,i);
        sort(a+1,a+T+1),solve(1,1,T,1,T);
        for(i=1;i<=tot;++i) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    Sign in with the app-specific password you generated. If you forgot the app-specific password or need to create a new one, go to appleid.apple.com
    Java Web项目搭建过程记录(struts2)
    微信小程序之菜鸟入门教学(二)
    微信小程序之菜鸟选手入门教学(一)
    html 表单input录入内容校验
    VUE中使用driver.js实现先手引导
    BScroll使用
    VUE使用screenfull实现全屏
    VUE打印功能
    VUE中使用XLSX实现导出excel表格
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11530331.html
Copyright © 2011-2022 走看看