HDOJ:6356-Glad You Came(线段树剪枝)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6356

 

解题心得:

  • 现在深深的知道了算法复杂度的重要了,这个题算复杂度的时候还要把一些常数也算出来,不然常数太大也容易凉凉阿。这个题的m的数量级比n的还要大一位,如果用离线对询问排序直接就TLE了。
  • 其实这个题就是一个区间更新的线段树,只不过记录一下最小值,如果最小值大于将要更新的值就直接跳出,在线段树上剪枝。然而很迷的是在把m的内存开小了,开成n了居然不RE而是TLE,坑死了。
//
//      ┏┛ ┻━━━━━┛ ┻┓
//      ┃       ┃
//      ┃   ━   ┃
//      ┃ ┳┛   ┗┳ ┃
//      ┃       ┃
//      ┃   ┻   ┃
//      ┃       ┃
//      ┗━┓   ┏━━━┛
//        ┃   ┃   神兽保佑
//        ┃   ┃   代码无BUG!
//        ┃   ┗━━━━━━━━━┓
//        ┃           ┣┓
//        ┃             ┏┛
//        ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
//          ┃ ┫ ┫   ┃ ┫ ┫
//          ┗━┻━┛   ┗━┻━┛
#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5;
const int maxm = 2e7+100;
typedef long long ll;
long long f[maxm];
int n,m;
unsigned int x,y,z,w;
struct NODE {
    ll Min,va;
}node[maxn];

void pre() {
    for(int i=1;i<=3*m;i++) {
        x = x ^ (x << 11);
        x = x ^ (x >> 4);
        x = x ^ (x << 5);
        x = x ^ (x >> 14);
        w = x ^ (y ^ z);
        x = y;
        y = z;
        z = w;
        f[i] = z;
    }
}

void init() {
    scanf("%d%d%u%u%u",&n,&m,&x,&y,&z);
    pre();
}

void pushdown(int root) {
    if(node[root].va == 0)
        return ;
    int chl = root<<1;
    int chr = root<<1|1;
    node[chl].va = max(node[chl].va, node[root].va);
    node[chr].va = max(node[chr].va, node[root].va);
    node[chl].Min = max(node[chl].Min, node[root].va);
    node[chr].Min = max(node[chr].Min, node[root].va);
    node[root].va = 0;
}

void updata(int root) {
    int chl = root<<1;
    int chr = root<<1|1;
    node[root].Min = min(node[chl].Min, node[chr].Min);
}

void change(int root,int ql, int qr, int l, int r,ll va) {
    if(va <= node[root].Min || r < ql || l > qr)
        return ;
    if(ql <= l && qr >= r) {
        node[root].va = max(node[root].va,va);
        node[root].Min = max(node[root].Min,va);
        return ;
    }
    pushdown(root);
    int mid = (l + r) >> 1;
    int chl = root<<1;
    int chr = root<<1|1;

    change(chl, ql, qr, l, mid, va);
    change(chr, ql, qr, mid+1, r, va);
    updata(root);
}

ll ans = 0;

void get_ans(int root,int l,int r) {
    if(l == r) {
        ans ^= 1ll * node[root].Min * l;
        return ;
    }
    pushdown(root);
    int mid = (l + r) >> 1;
    int chl = root<<1;
    int chr = root<<1|1;
    get_ans(chl, l, mid);
    get_ans(chr, mid+1, r);
}

int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        memset(node, 0, sizeof(node));
        init();
        for(int i=1;i<=m;i++) {
            ll l = min(f[3*i-2]%n+1, f[3*i-1]%n+1);
            ll r = max(f[3*i-2]%n+1, f[3*i-1]%n+1);
            ll v = f[3*i]%(1<<30);
            change(1, l, r, 1, n, v);
        }
        ans = 0;
        get_ans(1, 1, n);
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-08-12 09:37  GoldenFingers  阅读(287)  评论(0编辑  收藏  举报