zoukankan      html  css  js  c++  java
  • 【BZOJ 1178】【APIO 2009】CONVENTION会议中心

    http://www.lydsy.com/JudgeOnline/problem.php?id=1178

    这道题想了好久没想明白,倍增数组通过看题解很快就明白了,但是一小段区间内应有的最多线段数一直不知道怎么记录。

    后来聪哥提醒我才明白,直接getans(l,r)不就完了吗_(:з」∠)_根本不用记录啊QwQ

    我用splay维护线段的位置顺序,查找前驱后继等等。
    上午因为懒得写插入线段前判断线段将要覆盖的区间是否是空的,所以又写了一棵线段树。然后因为一个自以为是线段树写残了的错误,就把线段树删了QAQ

    后来才知道那个错误是因为代码宽度很大以至于最右边被遮住的一个部分因为减号打成了加号调了一下午(/= _ =)/~┴┴,最后还是写了splay查找前驱后继,调了一天了QAQ。我竟然把这种题当代码题做了!

    最后,最后一条线段的编号后面不能有空格,否则会PE

    时间复杂度$O(nlogn)$

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 200003;
    int in() {
    	int k = 0, fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 3) + (k << 1) + c - '0';
    	return k * fh;
    }
    
    struct Line {
    	int l, r;
    	bool operator < (const Line &A) const {
    		return r == A.r ? l > A.l : r < A.r;
    	}
    } L[N], Lf[N], F[N], lth, rth;
    int right[N << 1], cnt = 0, H[N << 1], n, tot, f[N][19], ans;
    
    int getans(int l, int r) {
    	l = right[l - 1]; int ret = 0;
    	for(int j = 18; j >= 0; --j)
    		if (f[l][j] <= r && f[l][j] != 0) {
    			ret += (1 << j);
    			l = right[f[l][j]];
    		}
    	return ret;
    }
    
    namespace Splay {
    	struct node *null;
    	struct node {
    		node *ch[2], *fa;
    		int l, r, s;
    		node(int left = 0, int right = 0) {
    			ch[0] = ch[1] = fa = null;
    			l = left; r = right; s = 1;
    		}
    		bool pl() {return fa->ch[1] == this;}
    		void setc(node *r, bool c) {ch[c] = r; r->fa = this;}
    		void count() {s = ch[0]->s + ch[1]->s + 1;}
    	} *root;
    	void rotate(node *r) {
    		node *f = r->fa;
    		bool c = r->pl();
    		if (f == root) root = r, r->fa = null;
    		else f->fa->setc(r, f->pl());
    		f->setc(r->ch[!c], c);
    		r->setc(f, !c);
    		f->count();
    	}
    	void splay(node *r, node *tar = null) {
    		for(; r->fa != tar; rotate(r))
    			if (r->fa->fa != tar) rotate(r->pl() == r->fa->pl() ? r->fa : r);
    		r->count();
    	}
    	void insert(int l, int r) {
    		bool c; node *now = root;
    		if (root == null) {
    			root = new node(l, r);
    			return;
    		}
    		while (1) {
    			if (l > now->r) c = true;
    			else if (r < now->l) c = false;
    			if (now->ch[c] == null) {
    				now->setc(new node(l, r), c);
    				splay(now->ch[c]);
    				return;
    			} else now = now->ch[c];
    		}
    	}
    	void init(int l, int r) {
    		null = new node();
    		null->ch[0] = null->ch[1] = null->fa = null;
    		null->s = 0;
    		root = null;
    		insert(l, l); insert(r, r);
    	}
    	Line query_l(node *now, int l, int tmp) {
    		if (now == null) return (Line) {0, -0x7fffffff};
    		if (now->r >= l) return query_l(now->ch[0], l, tmp);
    		else {
    			tmp += now->ch[0]->s + 1;
    			return max((Line) {tmp, now->r}, query_l(now->ch[1], l, tmp));
    		}
    	}
    	Line query_r(node *now, int r, int tmp) {
    		if (now == null) return (Line) {cnt, 0x7fffffff};
    		if (now->l <= r) return query_r(now->ch[1], r, tmp + now->ch[0]->s + 1);
    		else return min((Line) {tmp + now->ch[0]->s + 1, now->l}, query_r(now->ch[0], r, tmp));
    	}
    }
    
    int main() {
    	n = in();
    	for(int i = 1; i <= n; ++i) {
    		L[i].l = in(); L[i].r = in();
    		H[++cnt] = L[i].l; H[++cnt] = L[i].r;
    	}
    	sort(H + 1, H + cnt + 1);
    	cnt = unique(H + 1, H + cnt + 1) - H;
    	for(int i = 1; i <= n; ++i) {
    		L[i].l = lower_bound(H + 1, H + cnt, L[i].l) - H;
    		L[i].r = lower_bound(H + 1, H + cnt, L[i].r) - H;
    		F[i] = L[i];
    	}
    	sort(L + 1, L + n + 1);
    	
    	Lf[tot = 1] = L[1];
    	for(int i = 2; i <= n; ++i)
    		if (L[i].l > Lf[tot].l)
    			Lf[++tot] = L[i];
    	Lf[tot + 1].l = 0x7fffffff;
    	
    	int head, tail = tot;
    	for(head = cnt - 1; head > 0; --head) {
    		while (head < Lf[tail].l) --tail;
    		right[head] = tail + 1;
    	}
    	right[0] = 1;
    	
    	for(int i = 1; i <= tot; ++i) f[i][0] = Lf[i].r;
    	for(int j = 1; j <= 18; ++j)
    		for(int i = 1; i <= tot; ++i) {
    			if (f[i][j - 1] == 0 || (head = f[right[f[i][j - 1]]][j - 1]) == 0) continue;
    			f[i][j] = head;
    		}
    	
    	Splay::init(0, cnt);
    	printf("%d
    ", (ans = getans(1, cnt - 1)));
    	int l, r;
    	for(int i = 1; i <= n; ++i) {
    		lth = Splay::query_l(Splay::root, F[i].l, 0);
    		rth = Splay::query_r(Splay::root, F[i].r, 0);
    		if (rth.l - lth.l != 1) continue;
    		l = lth.r; r = rth.r;
    		if (getans(l + 1, F[i].l - 1) + getans(F[i].r + 1, r - 1) + 1 == getans(l + 1, r - 1)) {
    			printf("%d", i);
    			Splay::insert(F[i].l, F[i].r);
    			--ans;
    			if (ans) putchar(' ');
    		}
    	}
    	
    	puts("");
    	return 0;
    }
    

  • 相关阅读:
    小程序-文章:微信小程序常见的UI框架/组件库总结
    小程序-文章:微信第三方登录(静默授权和非静默授权)
    asterisk
    Java实现 洛谷 P1423 小玉在游泳
    Java实现 洛谷 P1423 小玉在游泳
    Java实现 洛谷 P1423 小玉在游泳
    Java实现 洛谷 P1035 级数求和
    Java实现 洛谷 P1035 级数求和
    Java实现 洛谷 P1035 级数求和
    Java实现 洛谷 P1035 级数求和
  • 原文地址:https://www.cnblogs.com/abclzr/p/5788299.html
Copyright © 2011-2022 走看看