• 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)


    【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)

    语文没学好不要写省选题面!!!!

    题目大意:

    (n)个集合,每个集合有个任意时刻都可用的初始元素。现在有(m)个操作

    • 询问([l,r])的集合中,使得(voplus x)最大的那个元素,输出(voplus x)。同时要求这个(x)是最近(d)次插入中插入的。
    • 在集合(i)中插入一个数(x)

    考虑这样一个做法,直接开一颗线段树,线段树每个节点是一个(trie)树(不用可持久化),维护节点代表的区间中的集合的所有元素构成的(trie)树。

    考虑时间复杂度

    • 每次询问被拆成(log n)个询问,加上(trie)的复杂度(O(n log^2n))
    • 每次插入也被拆成(log n)个插入,加上(trie)的复杂度(O(n log^2n))

    考虑空间复杂度

    • 考虑每个元素被插入了(O(log n))次,加上(trie)树就是(O(nlog^2 n))

    trie节点要开3e7个,就问你够不够暴力。

    7.59s / 288.88MB / 1.92KB C++11

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define mid ((l+r)>>1)
    #define lef L,R,l,mid,pos<<1
    #define rgt L,R,mid+1,r,pos<<1|1
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    const int maxn=1e5+5;
    const int inf=1e9+7;
    
    struct E{
          int son[2],cnt;
          E(){son[0]=son[1]=0;cnt=-inf;}
          inline int& operator[](int x){return son[x];}
    }dic[25000000];
    int seg[maxn<<2],cnt,n,m;
    
    inline void insert(const int&now,const int&x,const int&d){
          int k=now;
          dic[k].cnt=max(dic[k].cnt,d);
          for(int t=30;~t;--t){
    	    int f=x>>t&1;
    	    k=dic[k][f]?dic[k][f]:dic[k][f]=++cnt,dic[k].cnt=max(dic[k].cnt,d);
          }
    }
    
    int getans(const int&now,const int&x,const int&d){
          int k=now,ret=0;
          for(int t=30;~t;--t){
    	    int f=x>>t&1;
    	    if(dic[k][f^1]&&dic[dic[k][f^1]].cnt>=d) k=dic[k][f^1],ret|=1<<t;
    	    else k=dic[k][f];
          }
          return ret;
    }
    
    void upd(const int&x,const int&d,const int&L,const int&R,const int&l,const int&r,const int&pos){
          if(L>r||R<l)return;
          if(!seg[pos]) seg[pos]=++cnt;
          insert(seg[pos],x,d);
          if(l==r) return;
          upd(x,d,lef); upd(x,d,rgt);
    }
    
    int que(const int&ans,const int&d,const int&L,const int&R,const int&l,const int&r,const int&pos){
          if(L>r||R<l) return 0;
          if(L<=l&&r<=R) return getans(seg[pos],ans,d);
          return max(que(ans,d,lef),que(ans,d,rgt));
    }
    
    int main(){
          n=qr(); m=qr();
          int day=1;
          for(int t=1;t<=n;++t)
    	    upd(qr(),inf,t,t,1,n,1);
          for(int t=1,t1,t2,t3,t4;t<=m;++t)
    	    if(qr()) t1=qr(),t2=qr(),t3=qr(),t4=qr(),printf("%d
    ",que(t3,max(0,day-t4+1),t1,t2,1,n,1));
          	    else ++day,t1=qr(),t2=qr(),upd(t2,day,t1,t1,1,n,1);
          return 0;
    }
    
    
    
    
  • 相关阅读:
    pyqt 设置QTabWidget标签页不可选
    C#分块读取文本数据(FileStream)
    C#IO读写文本txt文件中的数据
    C#IO读写文本txt文件中的数据
    Winform开发主界面菜单的动态树形列表展示
    Winform开发主界面菜单的动态树形列表展示
    C#LinqJoin两个DataTable
    C#LinqJoin两个DataTable
    c#转义字符
    c#转义字符
  • 原文地址:https://www.cnblogs.com/winlere/p/11537692.html
Copyright © 2020-2023  润新知