zoukankan      html  css  js  c++  java
  • [BZOJ2683][BZOJ4066]简单题

    [BZOJ2683][BZOJ4066]简单题

    试题描述

    你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

    命令

    参数限制

    内容

    1 x y A

    1<=x,y<=N,A是正整数

    将格子x,y里的数字加上A

    2 x1 y1 x2 y2

    1<=x1<= x2<=N

    1<=y1<= y2<=N

    输出x1 y1 x2 y2这个矩形内的数字和

    3

    终止程序

    输入

    输入文件第一行一个正整数N。
    接下来每行一个操作。每条命令除第一个数字之外,
    均要异或上一次输出的答案last_ans,初始时last_ans=0。(BZOJ2683不需要强制在线)

    输出

    对于每个2操作,输出一个对应的答案。

    输入示例(BZOJ2683)

    4
    1 2 3 3
    2 1 1 3 3
    1 2 2 2
    2 2 2 3 4
    3

    输出示例(BZOJ2683)

    3
    5

    输入示例(BZOJ4066)

    4
    1 2 3 3
    2 1 1 3 3
    1 1 1 1
    2 1 1 0 7
    3

    输出示例(BZOJ4066)

    3
    5

    数据规模及约定

    1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。

    题解

    只有权限号可以享受的双倍经验题(雾)。

    2683这道数据水,最裸的kd树就卡时限过了。。。

    4066这题数据强,需要加一个定期重构,就是加入的元素达到了某一些固定值就暴力把整棵kd树重新构造一遍,这样就不会被卡成“n2 的优秀算法了”。

    2683(不强制在线无定期重构慢的要死):

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 200010
    #define oo 2147483647
    int root, ToT, lc[maxn], rc[maxn];
    struct Node {
    	int x[2], mx[2], mn[2], val, sum;
    	bool operator == (const Node& t) const { return x[0] == t.x[0] && x[1] == t.x[1]; }
    } nodes[maxn];
    
    Node x, y;
    void maintain(int o) {
    	int l = lc[o], r = rc[o];
    	for(int i = 0; i < 2; i++) {
    		nodes[o].mx[i] = max(max(nodes[l].mx[i], nodes[r].mx[i]), nodes[o].x[i]);
    		nodes[o].mn[i] = min(min(nodes[l].mn[i], nodes[r].mn[i]), nodes[o].x[i]);
    	}
    	nodes[o].sum = nodes[l].sum + nodes[r].sum + nodes[o].val;
    //	printf("maintain(%d): %d %d %d %d %d
    ", o, nodes[o].sum, nodes[o].mx[0], nodes[o].mn[0], nodes[o].mx[1], nodes[o].mn[1]);
    	return ;
    }
    void add(int& o, bool cur) {
    	if(!o){ nodes[o = ++ToT] = x; return maintain(o); }
    	if(nodes[o] == x){ nodes[o].val += x.val; nodes[o].sum += x.val; return maintain(o); }
    	add(x.x[cur] < nodes[o].x[cur] ? lc[o] : rc[o], cur ^ 1);
    	return maintain(o);
    }
    bool all(int o) { return x.x[0] <= nodes[o].mn[0] && nodes[o].mx[0] <= y.x[0] && x.x[1] <= nodes[o].mn[1] && nodes[o].mx[1] <= y.x[1]; }
    bool has(int o) { return !(nodes[o].mx[0] < x.x[0] || nodes[o].mn[0] > y.x[0] || nodes[o].mx[1] < x.x[1] || nodes[o].mn[1] > y.x[1]); }
    int query(int o) {
    	if(!o) return 0;
    	int ans = 0;
    	if(all(lc[o])) ans += nodes[lc[o]].sum;
    	else if(has(lc[o])) ans += query(lc[o]);
    	if(all(rc[o])) ans += nodes[rc[o]].sum;
    	else if(has(rc[o])) ans += query(rc[o]);
    	int nx = nodes[o].x[0], ny = nodes[o].x[1];
    	if(x.x[0] <= nx && nx <= y.x[0] && x.x[1] <= ny && ny <= y.x[1]) ans += nodes[o].val;
    	return ans;
    }
    
    int main() {
    	nodes[0].mx[0] = nodes[0].mx[1] = -oo;
    	nodes[0].mn[0] = nodes[0].mn[1] = oo;
    	nodes[0].val = nodes[0].sum = 0;
    	int n = read();
    	n = read();
    	while(n < 3) {
    		if(n == 1) {
    			x.x[0] = read(); x.x[1] = read(); x.val = read();
    			add(root, 1);
    		}
    		if(n == 2) {
    			x.x[0] = read(); x.x[1] = read(); y.x[0] = read(); y.x[1] = read();
    			printf("%d
    ", query(root));
    		}
    		n = read();
    	}
    	
    	return 0;
    }
    

    4066(强制在线加定期重构但还是很慢= =):

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 200010
    #define oo 2147483647
    int root, ToT, lc[maxn], rc[maxn];
    bool Cur;
    struct Node {
    	int x[2], mx[2], mn[2], val, sum;
    	bool operator == (const Node& t) const { return x[0] == t.x[0] && x[1] == t.x[1]; }
    	bool operator < (const Node& t) const { return x[Cur] < t.x[Cur]; }
    } nodes[maxn];
    
    Node x, y;
    void maintain(int o) {
    	int l = lc[o], r = rc[o];
    	for(int i = 0; i < 2; i++) {
    		nodes[o].mx[i] = max(max(nodes[l].mx[i], nodes[r].mx[i]), nodes[o].x[i]);
    		nodes[o].mn[i] = min(min(nodes[l].mn[i], nodes[r].mn[i]), nodes[o].x[i]);
    	}
    	nodes[o].sum = nodes[l].sum + nodes[r].sum + nodes[o].val;
    //	printf("maintain(%d): %d %d %d %d %d
    ", o, nodes[o].sum, nodes[o].mx[0], nodes[o].mn[0], nodes[o].mx[1], nodes[o].mn[1]);
    	return ;
    }
    void add(int& o, bool cur) {
    	if(!o){ nodes[o = ++ToT] = x; return maintain(o); }
    	if(nodes[o] == x){ nodes[o].val += x.val; nodes[o].sum += x.val; return maintain(o); }
    	add(x.x[cur] < nodes[o].x[cur] ? lc[o] : rc[o], cur ^ 1);
    	return maintain(o);
    }
    void build(int& o, int L, int R, int cur) {
    	if(L > R){ o = 0; return ; }
    	int M = L + R >> 1; o = M;
    	Cur = cur; nth_element(nodes + L, nodes + M, nodes + R + 1);
    	build(lc[o], L, M - 1, cur ^ 1); build(rc[o], M + 1, R, cur ^ 1);
    	return maintain(o);
    }
    bool all(int o) { return x.x[0] <= nodes[o].mn[0] && nodes[o].mx[0] <= y.x[0] && x.x[1] <= nodes[o].mn[1] && nodes[o].mx[1] <= y.x[1]; }
    bool has(int o) { return !(nodes[o].mx[0] < x.x[0] || nodes[o].mn[0] > y.x[0] || nodes[o].mx[1] < x.x[1] || nodes[o].mn[1] > y.x[1]); }
    int query(int o) {
    	if(!o) return 0;
    	int ans = 0;
    	if(all(lc[o])) ans += nodes[lc[o]].sum;
    	else if(has(lc[o])) ans += query(lc[o]);
    	if(all(rc[o])) ans += nodes[rc[o]].sum;
    	else if(has(rc[o])) ans += query(rc[o]);
    	int nx = nodes[o].x[0], ny = nodes[o].x[1];
    	if(x.x[0] <= nx && nx <= y.x[0] && x.x[1] <= ny && ny <= y.x[1]) ans += nodes[o].val;
    	return ans;
    }
    
    int main() {
    	nodes[0].mx[0] = nodes[0].mx[1] = -oo;
    	nodes[0].mn[0] = nodes[0].mn[1] = oo;
    	nodes[0].val = nodes[0].sum = 0;
    	int n = read(), lastans = 0;
    	n = read();
    	while(n < 3) {
    		if(n == 1) {
    			x.x[0] = read() ^ lastans; x.x[1] = read() ^ lastans; x.val = read() ^ lastans;
    			add(root, 1);
    			if(ToT % 1000 == 0) build(root, 1, ToT, 1);
    		}
    		if(n == 2) {
    			x.x[0] = read() ^ lastans; x.x[1] = read() ^ lastans; y.x[0] = read() ^ lastans; y.x[1] = read() ^ lastans;
    			printf("%d
    ", lastans = query(root));
    		}
    		n = read();
    	}
    	
    	return 0;
    }
    

    其实这道题我第一眼看上去是树套树删边题,结果一看内存限制20M。。。还好没写树套树= =

  • 相关阅读:
    轻奢侈品_百度百科
    什么是轻奢风?_百度知道
    Nitrous.IO融资665万美元 帮助开发者省去配置调试等工作-CSDN.NET
    Intro to Computer Science Class Online (CS101)
    (92) Web Crawling: How can I build a web crawler from scratch?
    zombie-phantom
    How to choose between zombie.js and PhantomJS for automated web testing? [closed]
    Zombie.js Insanely fast, headless full-stack testing using Node.js
    (92) Is there a better crawler than Scrapy?
    tpopela/vips_java
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5575953.html
Copyright © 2011-2022 走看看