zoukankan      html  css  js  c++  java
  • CF1265B Beautiful Numbers

    题意

    给一个长度为(n)的排列(P),求对于(1)(n)中的每个数(m),是否能找到一段长度为(m)的区间使得区间内的数是一个(1)(m)的排列。

    输出一个(01)串,其中第(i)位表示是否能找到一段长度为(i)的区间使得区间内的数是一个(1 - i)的排列

    (n leq 2e5)

    分析

    对于某个数,如果能找到一段区间使它合法,那么这个区间一定是唯一且连续的

    考虑从小到大对于每个数,查找它的位置,并维护当前所找到的位置的最小值和最大值,即维护一下当前区间的左端点和右端点

    当这个区间连续时,即(Max - Min + 1 = m)时,当前(m)是合法的

    于是现在变成了在一个无序的排列上查找一个数的位置,主席树+二分即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline int read() {
    	int cnt = 0, f = 1; char c = getchar();
    	while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    	while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
    	return cnt * f;
    }
    const int N = 200000 + 10;
    int T, n, a[N], L, R, p;
    int cur, rt[N], ls[N * 20], rs[N * 20], val[N * 20];
    void modify(int &x, int l, int r, int lst, int pos) {
    	x = ++cur;
    	ls[x] = ls[lst], rs[x] = rs[lst], val[x] = val[lst] + 1;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (pos <= mid) modify(ls[x], l, mid, ls[lst], pos);
    	else modify(rs[x], mid + 1, r, rs[lst], pos);
    }
    int query(int x, int l, int r, int pos) {
    	if (!x) return 0; if (l == r) return val[x];
    	int mid = (l + r) >> 1;
    	if (pos <= mid) return query(ls[x], l, mid, pos);
    	else return query(rs[x], mid + 1, r, pos);
    }
    void clear() {
    	for (register int i = 1; i <= cur; ++i) ls[i] = rs[i] = val[i] = 0;
    	memset(rt, 0, sizeof rt);
    	cur = 0; L = n + 1, R = 0;
    }
    int binary(int d) {
    	int l = 1, r = n;
    	int mid = (l + r) >> 1;
    	while (l < r) {
    		if (!query(rt[mid], 1, n, d)) l = mid + 1;
    		else r = mid;
    		mid = (l + r) >> 1;
    	} return l;
    }
    int main() {
    //	freopen("1.in", "r", stdin);
    	T = read();
    	while (T--) {
    		n = read();
    		clear();
    		for (register int i = 1; i <= n; ++i) a[i] = read(), modify(rt[i], 1, n, rt[i - 1], a[i]);
    		for (register int i = 1; i <= n; ++i) {
    			p = binary(i);
    			if (p < L) L = p;
    			if (p > R) R = p;
    			if (R - L + 1 == i) printf("1"); else printf("0");
    		} puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    [转载]c,c++及数据结构笔试题2(转)
    [转载]C,C++及数据结构笔试题1(转)
    C++指针详细解析
    [转载]转载一篇好文章:《海量数据处理常用思路和方法》
    [转载]c,c++及数据结构笔试题2(转)
    [转载]C++ 面试
    [转载]转载一篇好文章:《海量数据处理常用思路和方法》
    [转载]C,C++及数据结构笔试题1(转)
    BizTalk手动清除MessageBox数据库
    Linux中的时间和时间管理
  • 原文地址:https://www.cnblogs.com/kma093/p/11997192.html
Copyright © 2011-2022 走看看