zoukankan      html  css  js  c++  java
  • NOIP2017列队

    NOIP2017 列队

    题意:有一个(n imes m)的方阵,进行(q)次操作,每次将第((x,y))个学生出列,输出该学生的编号,并将队列先向左对齐,再向前对齐,最后把该学生放在空位((n,m))

    题目链接

    数据范围:(1<=n,m,q<=3e5)

    解法:

    动态开点线段树

    这道题第一眼就是进行线段树的区间操作,然而发现空间存不下,但操作次数小,考虑动态开点线段树。

    (n+1)棵线段树,前(n)棵储存每一行,最后一棵储存最后一列。

    空间复杂度:(O(qlogn)) 时间复杂度:(O(qlogn))

    记录一个(size)就可以用线段树维护进行过删除操作后的第(k)个数的问题了,该方法与在(treap)中查找第(k)大数的方法类似

    这道题对于代码实现的考察也较大。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define maxn 10000100
    #define ll long long
    int n, q;
    ll m;
    struct node
    {
    	ll val;
    	int lz, rz, sz;
    	#define lz(x) tree[x].lz
    	#define rz(x) tree[x].rz
    	#define val(x) tree[x].val
    	#define sz(x) tree[x].sz
    }tree[maxn];
    int root[300100], cnt[300100];
    ll now;
    int tot = 0;
    int get(int l, int r)
    {
    	if(now == n + 1)
    	{
    		if(r <= n) return r - l + 1;
    		if(l <= n) return n - l + 1;
    		return 0;
    	}
    	if(r < m) return r - l + 1;
    	if(l < m) return m - l;
    	return 0;
    }
    ll query(int &k, ll l, int r, int x)
    {
    	if(!k)
    	{
    		k = ++tot;
    		sz(k) = get(l, r);
    		if(l == r)
    		{
    		    if(now != n + 1)
    		    {
    			    val(k) = (now - 1) * m + l;
    		    }
    		    else val(k) = l * m;
    	    }
    	}
    	int mid = (l + r) >> 1;
    	if(l == r)
    	{
           sz(k) -= 1;
    	   return val(k);
        }
        ll ans = 0;
    	if(!lz(k))
    	{
    		if(get(l, mid) >= x)
    		{
    		    ans = query(lz(k), l, mid, x);
    		}
    	    else ans = query(rz(k), mid + 1, r, x - get(l, mid));
    	}
    	else
    	{
    		if(sz(lz(k)) >= x)
    		{
    		    ans = query(lz(k), l, mid, x);
    		}
    		else ans = query(rz(k), mid + 1, r, x - sz(lz(k)));
    	}
        sz(k) = ((!lz(k)) ? get(l, mid) : sz(lz(k))) + ((!rz(k)) ? get(mid + 1, r): sz(rz(k)));
    	return ans;
    }
    void update(int &k, int l, int r, int x, ll v)
    {
    	if(!k)
    	{
    		k = ++tot;
    		sz(k) = get(l, r);
    	}
    	if(l == r)
    	{
    	    sz(k) += 1;
    		val(k) = v; return;
    	}
    	int mid = (l + r) >> 1;
    	if(mid >= x) update(lz(k), l, mid, x, v);
    	if(mid < x) update(rz(k), mid + 1, r, x, v);
    	sz(k) = ((!lz(k)) ? get(l, mid) : sz(lz(k))) + ((!rz(k)) ? get(mid + 1, r): sz(rz(k)));
    	return;
    }
    int main()
    {
    	scanf("%d%lld%d", &n, &m, &q);
    	for(int i = 1; i <= q; i++)
    	{
    		int x, y;
    		scanf("%d%d", &x, &y);
    		if(y != m)
    		{
    			cnt[x] += 1;
    			cnt[n + 1] += 1;
    			now = x;
    			ll ans = query(root[x], 1, m + q, y);
    	        printf("%lld
    ", ans);
    	        now = n + 1;
    	        update(root[n + 1], 1, n + q, n + cnt[n + 1], ans);
    	        ans = query(root[n + 1], 1, n + q, x);
    	        now = x;
    			update(root[x], 1, m + q, m + cnt[x], ans);
    		}
    		else
    		{
    			cnt[n + 1] += 1; now = n + 1;
    			ll ans = query(root[n + 1], 1, n + q, x);
    			update(root[n + 1], 1, n + q, n + cnt[n + 1], ans);
    	 	    printf("%lld
    ", ans);
    	 	}
    	}
    	return 0;
    }
    
  • 相关阅读:
    go context
    go etcd
    go logs
    go config
    go tail
    kafka与zookeeper
    go kafka
    go mysql
    array_map array_walk
    单独配置的nginx mysql 重启
  • 原文地址:https://www.cnblogs.com/Akaina/p/11725888.html
Copyright © 2011-2022 走看看