zoukankan      html  css  js  c++  java
  • [CEOI2020 D2T1 / CF1403A] 权力药水The Potion of Great Power 题解

    我的CEOI作战记录&题解-洛谷博客

    我的CEOI作战记录&题解-cnblogs

    题目链接-luogu 题目链接-Codeforces

    观察数据范围,不难得出每组询问应当用 (O(D)) 的时间复杂度解决,并且需要注意常数.

    一开始的想法是直接暴力存每个点相邻的权值集合,然后每次修改更新一次权值,这样就可以有序地取出在时间 (t) 时节点 (x)(y) 相邻点的权值集合了.

    时空复杂度都是 (O(UD),) 会爆空间.

    那么我们其实就是要在可持久化的情况下支持 (O(D)) 取出每个点在某个时刻的 (O(D)) 个相邻点的权值,并且需要保证有序.

    一种写法是直接使用可持久化 (fhqTreap) 直接对每个点相邻的权值进行可持久化,空间常数和时间常数都比较大,我当场使用了这个做法,花了 (3) 个小时卡常.

    另一种写法是 (uoj) 群友口胡的: 对每个点按时间建线段树,然后在线段树上insert,用set记录集合.我没写过,不知道这个做法时间效率怎么样,不过这个做法空间相对较小.

    (fhqTreap) 做法代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100005,U = 200005;
    int n,d,m,h[N];
    const int V = U*60;
    struct Treap{
    	struct Node{ int lc,rc,pos,val,siz; }t[V]; int _cnt;
    	inline int New_node(int v){ ++_cnt,t[_cnt].val = v,t[_cnt].pos = rand(),t[_cnt].siz = 1; return _cnt; }
    	inline int Copy_node(int p){ return memcpy(t+(++_cnt),t+p,20),_cnt; }
    	inline void up(int o){ t[o].siz = t[t[o].lc].siz + t[t[o].rc].siz + 1; }
    	inline int getrnk(int p,int v){
    		static int ans; ans = 0;
    		while (p) if (t[p].val > v) p = t[p].lc; else ans += 1 + t[t[p].lc].siz,p = t[p].rc;
    		return ans;
    	}
    	inline void spilt(int p,int k,int &x,int &y){
    		if (!p){ x = y = 0; return;	}
    		if (t[t[p].lc].siz >= k) y = Copy_node(p),spilt(t[y].lc,k,x,t[y].lc),up(y);
    		else x = Copy_node(p),spilt(t[x].rc,k-t[t[x].lc].siz-1,t[x].rc,y),up(x);
    	}
    	inline int merge(int x,int y){
    		if (!x || !y) return x|y;
    		if (t[x].pos < t[y].pos){ x = Copy_node(x),t[x].rc = merge(t[x].rc,y),up(x); return x;}
    		y = Copy_node(y),t[y].lc = merge(x,t[y].lc),up(y); return y;
    	}
    	inline int add(int p,int v){
    		static int k,x,y; k = getrnk(p,v); spilt(p,k,x,y);
    		return merge(merge(x,New_node(v)),y);
    	}
    	inline int del(int p,int v){
    		static int k,x,y,z; k = getrnk(p,v); spilt(p,k,x,y); spilt(x,k-1,x,z);
    		return merge(x,y);
    	}
     	int aa[505],llen;
    	inline void Get(int rt){ if (t[rt].lc) Get(t[rt].lc); aa[++llen] = t[rt].val; if (t[rt].rc) Get(t[rt].rc); }
    	inline void getall(int rt,int *a,int &len){
    		if (!rt) len = 0; else llen = 0,Get(rt),len = llen,memcpy(a,aa,len+1<<2);
    	}
    }Tr;
    vector<int>G[N],Gt[N];
    inline int query(int x,int t){
    	int L = 1,R = Gt[x].size()-1,Mid,Ans = 0;
    	while (L <= R){
    		Mid = L+R>>1;
    		if (Gt[x][Mid] <= t) Ans = G[x][Mid],L = Mid + 1; else R = Mid - 1;
    	}
    	return Ans;
    }
    int ans,lena,lenb,a[505],b[505];
    inline void upd(int x){ x < ans ? ans = x : 0; }
    inline void QUery(){
    	static int x,y,t,i,j;
    	cin >> x >> y >> t,++x,++y,ans = 1000000000;
    	Tr.getall(query(x,t),a,lena); Tr.getall(query(y,t),b,lenb);
    	i = j = 1;
    	while (i < lena && j < lenb) if (a[i] < b[j]) upd(b[j]-a[i]),++i; else upd(a[i]-b[j]),++j;
    	if (i == lena){ while (j <= lenb) upd((a[i] > b[j]) ? (a[i] - b[j]) : (b[j] - a[i])),++j; }
    	else if (j == lenb){ while (i <= lena) upd((a[i] > b[j]) ? (a[i] - b[j]) : (b[j] - a[i])),++i; }
    	cout << ans << '
    '; fflush(stdout);
    }
    set<int>S[N];
    int main(){
    	int i,q,x,y,vx,vy,t;
    	srand(time(NULL));
    	cin >> n >> d >> m >> q;
    	for (i = 1; i <= n; ++i) cin >> h[i];
    	for (i = 1; i <= n; ++i) G[i].push_back(0),Gt[i].push_back(0);
    	for (i = 1; i <= m; ++i){
    		cin >> x >> y,++x,++y; if (x > y) swap(x,y); vx = h[x],vy = h[y];
    		Gt[x].push_back(i),Gt[y].push_back(i);
    		if (S[x].count(y)){//have -> none
    			S[x].erase(y);
    			G[x].push_back(Tr.del(G[x].back(),vy));
    			G[y].push_back(Tr.del(G[y].back(),vx));
    		}
    		else{//none -> have
    			S[x].insert(y);
    			G[x].push_back(Tr.add(G[x].back(),vy));
    			G[y].push_back(Tr.add(G[y].back(),vx));
    		}
    	}
    	while (q--) QUery();
    	return 0;
    }
    
  • 相关阅读:
    STL堆算法性能分析与优化方法(GCC4.4.2 stl_heap.h源代码分析与改进方案)
    POJ 1631 Bridging Singnals
    一个用于读unicode文本的迭代器(iterator)
    常用文本压缩算法及实现(To be finshed!)
    volatile语义及线程安全singleton模式探讨
    C++实现的huffman与canonical huffman的压缩解压缩系统,支持基于单词的压缩解压缩
    linux环境下 C++性能测试工具 gprof + kprof + gprof2dot
    多线程统计多个文件的单词数目C++0x多线程使用示例
    python嵌入C++ boost.python如何在C++中调用含有不定长参数tuple变量和关键字参数dict变量的函数
    boost.python入门教程 python 嵌入c++
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13591187.html
Copyright © 2011-2022 走看看