zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 56 (Rated for Div. 2) G题(线段树,曼哈顿距离)

    题目传送门
    以二维为例,二维下两点间的曼哈顿距离最大值为(max(|x_i-x_j| + |y_i-y_j|)),可以通过枚举坐标符号正负来去掉绝对值。即(max(x_i-x_j+y_i-y_j,x_i+x_j+y_i-y_j...))共16种情况。设(f[i][t])表示第(i)个点各维度数值正负状态为(t)时的值,假如二维向量(p[i]=(1,2)),那么状态(t)的范围为([0,3]),如果(t=2),即二进制表示为(10),那么(p)向量第一维数值加个负号,第二维数值不变,类似状压过程。对于每个向量处理出(f)的值。最终结果即在([l,r])范围内求(max(f[i][m],f[j][n])(m+n=(1<<k)-1)),具体用线段树实现。

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    using namespace std;
    const int N = 2e5 + 50;
    
    struct Node{
        vector<int> val;
        Node() { val.resize(35); }
    }node[N << 2];
    
    int n, k, q;
    int a[N][6];
    
    void Max(const vector<int> &x, const vector<int> &y, vector<int> &z){
        for(int i = 0; i < (1 << k); ++i)  z[i] = max(x[i], y[i]);
    }
    
    void Max(const vector<int> &x, vector<int> &y){
        for(int i = 0; i < (1 << k); ++i)  y[i] = max(x[i], y[i]);
    }
    
    void build(int u, int l, int r){
        if(l == r){
            for(int s = 0; s < (1 << k); ++s){
                for(int t = 1; t <= k; ++t){
                    if(s & (1 << (t - 1)))  node[u].val[s] += a[l][t];
                    else  node[u].val[s] -= a[l][t];
                }
            }
            return ;
        }
        int mid = (l + r) >> 1;
        if(l <= mid)  build(ls, l, mid);
        if(r > mid)  build(rs, mid + 1, r);
        Max(node[ls].val, node[rs].val, node[u].val);
    }
    
    void modify(int u, int l, int r, int pos){
        if(l == r){
        	for(int i = 0; i < (1 << k); ++i)   node[u].val[i] = 0;
            for(int s = 0; s < (1 << k); ++s){
                for(int t = 1; t <= k; ++t){
                    if(s & (1 << (t - 1)))  node[u].val[s] += a[l][t];
                    else  node[u].val[s] -= a[l][t];
                }
            }
            return ;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)  modify(ls, l, mid, pos);
        else  modify(rs, mid + 1, r, pos);
        Max(node[ls].val, node[rs].val, node[u].val);
    }
    
    vector<int> ans(35);
    
    void query(int u, int l, int r, int ql, int qr){
    	if(ql <= l && qr >= r){
            Max(node[u].val, ans);
            return ;        
        }
        int mid = (l + r) >> 1;
        if(ql <= mid)  query(ls, l, mid, ql, qr);
        if(qr > mid)  query(rs, mid + 1, r, ql, qr);
    }
    
    int main(){
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i)
            for(int t = 1; t <= k; ++t)
                scanf("%d", &a[i][t]);
        build(1, 1, n);
        scanf("%d", &q);
        while(q--){
            int opt, id, l, r;
            scanf("%d", &opt);
            if(opt == 1){
                scanf("%d", &id);
                for(int i = 1; i <= k; ++i)  scanf("%d", &a[id][i]);
                modify(1, 1, n, id);
            }
            else{
                for(int i = 0; i < 35; ++i)  ans[i] = -1e9;
                scanf("%d%d", &l, &r);
                query(1, 1, n, l, r);
                int maxx = 0;
                for(int s = 0; s < (1 << k); ++s){
                    maxx = max(maxx, ans[s] + ans[(1 << k) - 1 - s]);
                }
                printf("%d
    ", maxx);  
            }
        }
    }
    
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    python-configparser模块,xml.etree模块
    Ubuntu16.04环境下Vim 配置 for HTML,CSS,JAVASCRIPT(1)
    Windows 命令行及Git操作
    Ubuntu16.04 无任务栏问题
    ubuntu16.04安装中文输入法
    本地Web服务器搭建
    爬虫(1)
    Python(四):数字连珠2
    python学习(四)五数连珠
    Openjudge 百练第4109题
  • 原文地址:https://www.cnblogs.com/214txdy/p/14278674.html
Copyright © 2011-2022 走看看