• P4855 MloVtry的idea


    $ color{#0066ff}{ 题目描述 }$

    MloVtry是一个脑洞很大的人,它总会想出一些奇奇怪怪的idea。

    可问题是,MloVtry作为一个蒟蒻,很多时候都没办法解决自己提出的问题,所以MloVtry想出一套题的梦想一直被搁置。

    不过好在MloVtry有一些神犇朋友,他们强的没边,所以MloVtry一有机会就会向这些dalao们请教。

    现在MloVtry有n个idea,这n个idea在MloVtry二维的大脑里排成一列,每一个idea都有一个难度值,用a[i]表示,当然难度值越大越困难。

    MloVtry准备与q个神犇进行交♂易,但是MloVtry不想问一些过于简单的idea来降自己的B格,又不好意思用太难的、无法解决的idea来伤害自己与神犇之间的感情,所以它每次都会挑idea序列中的第k简单的idea来向神犇询问(也就是难度值第k小的那个idea)。

    MloVtry的脑子有坑,但是没关系,这个坑会反而会帮助MloVtry思考,不过这样数列的a[i]就会更新,具体的,设坑在第j个idea上,那么a[i]=a[i]-zz(i<=j);a[i]=i+a[i]-j(i>j)。

    如果仅仅如此MloVtry也不会感到迷茫,但关键的是这个坑还会不定时的跳跃,这就让MloVtry手足无措了---它不知道这个时候要问哪个问题了。

    现在MloVtry会给出你---它最好的朋友一些询问---一些二元组(at,k),表示脑洞位于at,且它想询问第k简单的idea,请你告诉MloVtry这个idea难度是多少。

    (color{#0066ff}{输入格式})

    第一行三个整数n,q,zz,含义见题面

    第二行n个整数a[1],a[2].....a[n]

    随后q行,每行两个整数表示at与k

    特别的,MloVtry是一个三维生物,所以它无法想象有人可以在时间轴上翻滚,所以at与k与上一个询问的答案的绝对值的异或值并对n取膜后再+1的值为本次的at和k。

    (也就是设lastans为上次询问答案,每一次at=(at^abs(lastans))%n+1,k=(k^abs(lastans))%n+1,并将lastans更新,初始lastans=0)

    (color{#0066ff}{输出格式})

    q行q个整数,表示对每个询问的回答

    (color{#0066ff}{输入样例})

    13 12 56
    10100 12208 11766 11872 11336 10815 10710 11872 11536 11988 10100 10908 10815 
    11 13
    1 3
    3 10
    1 7
    8 4
    7 11
    11 4
    5 2
    13 11
    13 6
    3 11
    11 10
    

    (color{#0066ff}{输出样例})

    10044
    11932
    10918
    11280
    10044
    10759
    10827
    11874
    12152
    10759
    10044
    10713
    

    (color{#0066ff}{数据范围与提示})

    各个值保证在int范围内。

    对于100%的数据,n,q<=6w。

    对于40%的数据,n,q<=1000。

    PS.可能有重复,例如

    1 1 1 1 1 0

    此时第1大、第2大....第5大的值都是1,第6大的值是0

    (color{#0066ff}{题解})

    对序列(a[i]-zz和a[i]+i)分别开一个主席树

    然后对于每次询问, 二分答案,分别在两个主席树上找(le mid和le mid+at)的数的个数,从而缩小范围

    总复杂度(O(nlog^2n))

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int inf = 0x7fffffff;
    const int maxn = 1e5 + 10;
    struct Tree {
    protected:
    	struct node {
    		node *ch[2];
    		int num;
    		node(int num = 0): num(num) { ch[0] = ch[1] = NULL; }
    	}*root[maxn];
    	int L, R;
    	void add(node *&o, node *lst, int l, int r, int pos) {
    		o = new node();
    		*o = *lst;
    		o->num++;
    		if(l == r) return;
    		LL mid = ((LL)(l + r)) >> 1;
    		if(pos <= mid) add(o->ch[0], lst->ch[0], l, mid, pos);
    		else add(o->ch[1], lst->ch[1], mid + 1, r, pos);
    	}
    	int query(node *x, node *y, int ql, int qr, int l, int r) {
    		if(ql <= l && r <= qr) return y->num - x->num;
    		if(x->num == y->num) return 0;
    		LL mid = ((LL)(l + r)) >> 1, ans = 0;
    		if(ql <= mid) ans += query(x->ch[0], y->ch[0], ql, qr, l, mid);
    		if(qr > mid) ans += query(x->ch[1], y->ch[1], ql, qr, mid + 1, r);
    		return ans;
    	}
    public:
    	Tree() { 
    		root[0] = new node();
    		root[0]->ch[0] = root[0]->ch[1] = root[0];
    	}
    	void resize(int l, int r) { L = l, R = r; }
    	void init(int n, int *a) { for(int i = 1; i <= n; i++) add(root[i], root[i - 1], L, R, a[i]); }
    	int query(int l, int r, int val) { return query(root[l - 1], root[r], L, val, L, R); }
    }f, g;
    int a[maxn], b[maxn];
    int abs(int x) { return x > 0? x : -x; }
    int main() {
    	int n = in(), q = in(), zz = in();
    	int max = -inf, min = inf;
    	for(int i = 1; i <= n; i++) {
    		a[i] = in();
    		b[i] = a[i] + i;
    		a[i] = a[i] - zz;
    		max = std::max(max, std::max(a[i], b[i]));
    		min = std::min(min, std::min(a[i], b[i]));
    	}
    	f.resize(min, max), g.resize(min, max);
    	f.init(n, a), g.init(n, b);
    	int at, k, ans = 0;
    	while(q --> 0) {
    		at = (in() ^ abs(ans)) % n + 1;
    		k = (in() ^ abs(ans)) % n + 1;
    		LL l = min, r = max;
    		while(l <= r) {
    			LL mid = (l + r) >> 1;
    			if(k <= f.query(1, at, mid) + g.query(at + 1, n, mid + at)) r = mid - 1, ans = mid;
    			else l = mid + 1;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    快逸报表调用存储过程(SqlServer)
    一个睡五分钟等于六个钟头的方法 (转)
    Windows Live Writer For Windows Server 2003
    设计模式装饰者模式
    SqlServerCUBE
    Android 70道面试题汇总不再愁面试
    说服力:让你的PPT会说话
    亮剑Java项目开发案例导航
    初入社会必知的88个潜规则
    android UI进阶之仿iphone的tab效果2
  • 原文地址:https://www.cnblogs.com/olinr/p/10461537.html
Copyright © 2020-2023  润新知