zoukankan      html  css  js  c++  java
  • 【洛谷】P4585 [FJOI2015]火星商店问题

    题解

    题目太丧,OJ太没有良心,我永远喜欢LOJ!
    (TLE报成RE,垃圾洛谷,我永远喜欢LOJ)

    好的,平复一下我debug了一上午崩溃的心态= =,写一写这道题的题解

    把所有限制去掉,给出一个值,和一堆数种选一个异或起来求最大值,是一个经典的字典树问题,如果去掉了d的限制,我们类似主席树那样求一个可持久化字典树,利用前缀和就可以快速求得一个区间的字典树了,所以对于所有特殊商品,我们先用这些商品更新一下每一个询问

    我们可以用线段树套可持久化trie树,然而空间很难办……
    那么我们转为对每个线段树的区间,处理所有覆盖这个区间的询问就好了

    对于所有后加的商品,按照商店编号排序
    然后我们对于时间进行二分,二分到一个时间区间[L,R]

    然后我们拿到这个区间里的商品建出一个trie树,然后找到所有询问里能完整覆盖整个时间区间的询问,更新这个询问的答案
    再把询问分到左右区间去分治

    代码

    #include <bits/stdc++.h>
    #define MAXN 100005
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N,M;
    int a[MAXN];
    int ch[MAXN * 40][2],Ncnt,rt[MAXN * 2],siz[MAXN * 40],ans[MAXN * 2],cntq,cnti,D,num[MAXN],MK;
    struct qry_node {
        int L,R,sl,sr,val,id;
    }qry[MAXN],tmp[MAXN];
    struct change_node {
        int s,t,v;
        friend bool operator < (const change_node &a,const change_node &b) {
    	return a.s < b.s;
        }
    }item[MAXN],DO[MAXN];
    void Insert(const int x,int &y,int v,int d) {
        
        y = ++Ncnt;
        ch[y][0] = ch[x][0],ch[y][1] = ch[x][1];
        siz[y] = siz[x];
        ++siz[y];
        if(d < 0) return;
        if(v >> d & 1) Insert(ch[x][1],ch[y][1],v,d - 1);
        else Insert(ch[x][0],ch[y][0],v,d - 1);
    }
    int query(int x,int L,int R) {
        L = rt[L];R = rt[R];
        int res = 0;
        for(int i = 16 ; i >= 0 ; --i) {
    	if(x >> i & 1) {
    	    if(siz[ch[R][0]] > siz[ch[L][0]]) res |= 1 << i,R = ch[R][0],L = ch[L][0];
    	    else R = ch[R][1],L = ch[L][1];
    	}
    	else {
    	    if(siz[ch[R][1]] > siz[ch[L][1]]) res |= 1 << i,R = ch[R][1],L = ch[L][1];
    	    else R = ch[R][0],L = ch[L][0];
    	}
        }
        return res;
    }
    void Init() {
        read(N);read(M);
        for(int i = 1 ; i <= N ; ++i) read(a[i]);
        for(int i = 1 ; i <= N ; ++i) {
    	Insert(rt[i - 1],rt[i],a[i],16);
        }
        int op,l,r,x,d;
        for(int i = 1 ; i <= M ; ++i) {
    	read(op);
    	if(op == 1) {
    	    read(l);read(r);read(x);read(d);
    	    ans[i] = query(x,l - 1,r);
    	    if(D != 0 && d != 0) {
    		qry[++cntq] = (qry_node){l,r,max(1,D - d + 1),D,x,i};
    	    }
    	}
    	else {
    	    ++D;
    	    ans[i] = -1;
    	    read(x);read(d);
    	    item[++cnti] = (change_node){x,D,d};
    	}
        }
        sort(item + 1,item + cnti + 1);
    }
    void work(int l,int r) {
        Ncnt = 0;
        MK = 0;
        num[0] = 0;
        for(int i = l ; i <= r ; ++i){
    	++MK;
    	Insert(rt[MK - 1],rt[MK],item[i].v,16);
    	num[MK] = item[i].s;
        }
    }
    int find(int x) {
        int l = 0,r = MK;
        
        while(l < r) {
    	int mid = (l + r + 1) >> 1;
    	if(num[mid] <= x) l = mid;
    	else r = mid - 1;
        }
        return l;
    }
    void Solve(int cl,int cr,int tl,int tr,int tot) {
        if(!tot || cr < cl) return;
        work(cl,cr);
        for(int i = 1 ; i <= tot ; ++i) {
    	if(qry[i].sl <= tl && qry[i].sr >= tr) {
    	    int l = find(qry[i].L - 1);
    	    int r = find(qry[i].R);
    	    ans[qry[i].id] = max(ans[qry[i].id],query(qry[i].val,l,r));
    	}
        }
        
        int MID = (tl + tr) >> 1;
        if(tl == tr) return;
        int p = 0,q = tot;
        for(int i = 1 ; i <= tot ; ++i) {
    	if(qry[i].sl <= tl && qry[i].sr >= tr) tmp[q--] = qry[i];
    	else if(qry[i].sl <= MID) tmp[++p] = qry[i];
    	else tmp[q--] = qry[i];
        }
        for(int i = 1 ; i <= tot ; ++i) qry[i] = tmp[i];
        int mk = cl,c;
        for(int i = cl ; i <= cr ; ++i) if(item[i].t <= MID) DO[mk++] = item[i];
        c = mk - cl;
        for(int i = cl ; i <= cr ; ++i) if(item[i].t > MID) DO[mk++] = item[i];
        for(int i = cl ; i <= cr ; ++i) item[i] = DO[i];
        Solve(cl,cl + c - 1,tl,MID,p);
        p = 0,q = tot;
        for(int i = 1 ; i <= tot; ++i) {
    	if(qry[i].sl <= tl && qry[i].sr >= tr) tmp[q--] = qry[i];
    	else if(qry[i].sr > MID) tmp[++p] = qry[i];
    	else tmp[q--] = qry[i];
        }
        for(int i = 1 ; i <= tot ; ++i) qry[i] = tmp[i];
        Solve(cl + c,cr,MID + 1,tr,p);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve(1,cnti,1,D,cntq);
        for(int i = 1 ; i <= M ; ++i) {
    	if(ans[i] != -1) out(ans[i]),enter;
        }
        //out(clock());enter;
        return 0;
    }
    
  • 相关阅读:
    Go语言环境配置 Sublime Text + GoSublime+ gocode + MarGo组合
    Java中string拼接,StringBuilder,StringBuffer和+
    java调优随记-java对象大小
    java调优随记-堆和栈
    java中一直说一个汉字使用两个字节,原来是不准确的
    kv存储对抗关系型数据库
    记一篇
    变态的静态资源缓存与更新
    git add shh public key
    hashmap 的最优访问
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9149774.html
Copyright © 2011-2022 走看看