zoukankan      html  css  js  c++  java
  • [SCOI2016]美味

    嘟嘟嘟


    看到这种区间问题和最大异或和,我刚开始想到可持久化trie(虽然我不会写)。
    但是这道题给的是(b_i) XOR ((a_j + x_i)),好像搞不了。
    不过大体思路跟普通的最大异或和还是比较像的:我们从高位向低位枚举,如果该位是(0),就看看有没有(1)
    假设第(i)位是(0),在第(i)位之前已经求得的答案是ans,那么我们希望得到的数是now = ans + (1 << i)。所以就要在[now - x, now - x + (1 << i) - 1]这个区间里查找是否存在(a_j),如果存在,说明这一位可以满足。
    查找的时候用主席树就好了。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 4e6 + 5;
    const int maxN = 1e5;	
    inline ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), last = ' ';
    	while(!isdigit(ch)) {last = ch; ch = getchar();}
    	while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
    	if(last == '-') ans = -ans;
    	return ans;
    }
    inline void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int n, m;
    struct Tree
    {
    	int ls, rs, sum;
    }t[maxn];
    int root[maxn], cnt = 0;
    In void update(int old, int& now, int l, int r, int id)
    {
    	t[now = ++cnt] = t[old];
    	++t[now].sum;
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(id <= mid) update(t[old].ls, t[now].ls, l, mid, id);
    	else update(t[old].rs, t[now].rs, mid + 1, r, id);
    }
    In int query(int old, int now, int l, int r, int L, int R)
    {
    	if(l == L && r == R) return t[now].sum - t[old].sum;
    	int mid = (l + r) >> 1;
    	if(R <= mid) return query(t[old].ls, t[now].ls, l, mid, L, R);
    	else if(L > mid) return query(t[old].rs, t[now].rs, mid + 1, r, L, R);
    	else return query(t[old].ls, t[now].ls, l, mid, L, mid) + query(t[old].rs, t[now].rs, mid + 1, r, mid + 1, R);
    }
    
    In bool Find(int old, int now, int L, int R)
    {
    	L = max(L, 0); R = min(R, maxN);
    	if(L > R) return 0;
    	return query(old, now, 0, maxN, L, R);
    }
    int main()
    {
    	n = read(); m = read();
    	for(int i = 1, x; i <= n; ++i) x = read(), update(root[i - 1], root[i], 0, maxN, x);
    	for(int i = 1; i <= m; ++i)
    	{
    		int b = read(), x = read(), L = read(), R = read(), ans = 0;
    		for(int j = 17; j >= 0; --j)
    		{
    			int now = ans + ((1 ^ ((b >> j) & 1)) << j);
    			if(Find(root[L - 1], root[R], now - x, now - x + (1 << j) - 1)) ans = now;
    			else ans += (((b >> j) & 1) << j);
    		}
    		write(b ^ ans), enter;
    	}
    	return 0;
    }
    
  • 相关阅读:
    变量的创建和初始化
    HDU 1114 Piggy-Bank (dp)
    HDU 1421 搬寝室 (dp)
    HDU 2059 龟兔赛跑 (dp)
    HDU 2571 命运 (dp)
    HDU 1574 RP问题 (dp)
    HDU 2577 How to Type (字符串处理)
    HDU 1422 重温世界杯 (dp)
    HDU 2191 珍惜现在,感恩生活 (dp)
    HH实习 acm算法部 1689
  • 原文地址:https://www.cnblogs.com/mrclr/p/10172091.html
Copyright © 2011-2022 走看看