zoukankan      html  css  js  c++  java
  • CF1093G Multidimensional Queries

    这题妙啊。
    学会了一个新(trick)

    题解

    [|x_1 - x_2|+|y_1 - y_2| = \ max (x_1-x_2+y_1-y_2,x_1-x_2-y_1+y_2,-x_1+x_2+y_1-y2,-x_1+x_2-y_1+y_2) = \max((x_1+y_1)-(x_2+y_2),(x_1-y_1)-(x_2-y_2),(-x_1+x_2)-(-y_1+y_2),(-x_1-y_1)-(-x_2-y_2)) ]

    得到两个信息。

    • 两个点的曼哈顿距离(|x_1-x_2|+|y_1-y_2|+|z_1-z_2|+dots = sum^{...}_{x,y,z...}max(x_1-x_2,x_2-x_1))
    • (x_1)前为(+)号,(x_2)前必定是(-)号。

    由于这个题目里(k <= 5),可以枚举每一个点的(x,y,zdots)坐标给答案贡献时前面的符号,可以用二进制来状压。那么对应的,另一个取得的点的状态就是这个点取反。(由第二个性质知道)。所以对每个点分别维护(2^k)个状态下的数值和,用线段树维护即可。最后的答案就是把询问区间的状态取出来,枚举每个状态下最大和再加上它取反的状态下最大和就是最大的答案了。

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    #define R register
    #define LL long long
    const int inf = 0x3f3f3f3f;
    const int MAXN = 2e5 + 10;
    
    inline int read() {
    	char a = getchar(); int x = 0,f = 1;
    	for(; a > '9' || a < '0'; a = getchar()) if(a == '-') f = -1;
    	for(; a >= '0' && a <= '9' ;a = getchar()) x = x * 10 + a - '0';
    	return x * f;
    }
    
    int n, k;
    int a[MAXN][5];
    int mx[MAXN << 2][32];
    
    struct Node { 
    	Node() { memset(s, 0, sizeof(s)); }
    	int s[32]; 
    };
    
    inline int ls(int x) { return x << 1; }
    inline int rs(int x) { return x << 1 | 1; }
    
    inline void update(int x) {
    	for(R int S = (1 << k) - 1; S >= 0 ; S --) mx[x][S] = max(mx[ls(x)][S], mx[rs(x)][S]);
    }
    
    inline void build(int x, int l, int r) {
    	if(l == r) {
    		for(R int S = (1 << k) - 1; S >= 0 ; S --) {
    			mx[x][S] = 0;
    			for(R int i = 0; i < k; i ++)
    				if((1 << i) & S) mx[x][S] += a[l][i];
    				else mx[x][S] -= a[l][i];
    		}
    		return ;
    	}	
    	int mid = l + r; mid >>= 1;
    	build(ls(x), l, mid); build(rs(x), mid + 1, r);
    	update(x);
    }
    
    int st[5];
    
    inline void modify(int x, int l, int r, int ad) {
    	if(l == r) {
    		for(R int i = 0; i < k; i ++) st[i] = read();
    		for(R int S = (1 << k) - 1; S >= 0 ; S --) {
    			mx[x][S] = 0;
    			for(R int i = 0; i < k; i ++)
    				if((1 << i) & S) mx[x][S] += st[i];
    				else mx[x][S] -= st[i];
    		}
    		return ;
    	}
    	int mid = l + r; mid >>= 1;
    	if(ad <= mid) modify(ls(x), l, mid, ad);
    	else modify(rs(x), mid + 1, r, ad);
    	update(x);
    }
    
    inline Node ask(int x, int l, int r, int Le, int Ri) {
    	if( Le <= l && r <= Ri ) {
    		Node ans;
    		for(R int S = (1 << k) - 1; S >= 0 ; S --) {
    			ans.s[S]= mx[x][S];
    		}
    		return ans;
    	}
    	int mid = l + r; mid >>= 1;
    	/*if(Le <= mid) ans = max(ans, ask(ls(x), l, mid, Le, Ri));
    	if(Ri > mid) ans = max(ans, ask(rs(x), mid + 1, r, Le, Ri));*/
    	if(Ri <= mid) return ask(ls(x), l, mid, Le, Ri);
    	if(Le > mid) return ask(rs(x), mid + 1, r, Le, Ri);
    	Node la = ask(ls(x), l, mid, Le, Ri);
    	Node ra = ask(rs(x), mid + 1, r, Le, Ri);
    	for(R int S = ( 1 << k ) - 1; S >= 0; S --) {
    		la. s[S] = max(la. s[S], ra. s[S]);
    	}
    	return la; 
    }
    
    int main() {
    	//freopen("a.in","r",stdin);
    	//freopen("a.out","w",stdout);
    	n = read(); k = read();
    	for(R int i = 1; i <= n; i ++) {
    		for(R int j = 0; j < k; j ++)
    			a[i][j] = read();
    	}
    	build(1, 1, n);
    	int q = read();
    	while(q --) {
    		if(read() == 1) {
    			int i = read();
    			modify(1, 1, n, i);
    		}
    		else {
    			int l = read(), r = read();
    			Node ans = ask(1, 1, n, l, r);
    			int res = 0;
    			for(R int S = ( 1 << k ) - 1; S >= 0; S --)
    				res = max( res, ans.s[S] + ans.s[((1 << k) - 1) ^ S]);
    			printf("%d
    ",res);
    		}
    	}
    	return 0;	
    }
    
  • 相关阅读:
    linux分析工具之vmstat详解
    linux分析工具之top命令详解
    hadoop之yarn详解(命令篇)
    hadoop之yarn详解(基础架构篇)
    linux分析利刃之sar命令详解
    hadoop之mapreduce详解(优化篇)
    linux之find命令详解
    一个毫无用处的公众号封面生成器
    一个简单的计时器对比各种可迭代对象定义方式的速度区别
    python中的迭代器和生成器
  • 原文地址:https://www.cnblogs.com/clover4/p/12901331.html
Copyright © 2011-2022 走看看