Tag-树状数组

Icontofig 's Blog // 我们的征程是星辰大海!Away From OI,Come to ICPC(查看友链请点About Me)

 2019-02-27 23:53:01 |  0 Comments  |  树状数组

BZOJ 1537 POI2005 AUT-The Bus 二维偏序问题

由于格式问题,这道题的题面就不往这里放了,给一个洛谷的链接吧:

[POI2005]AUT-The Bus

题解

这道题有中文题意,没有BZOJ权限号的可以去洛谷上搜到这道题。
首先会想到DP,但是一看这个数据范围也太大了,离散化后也没法做二维DP。
但是离散化也是要的,不然10的9次方的数据谁顶得住啊。
考虑这是一个二维偏序问题。一般的二维偏序都是找比当前物品的两个值都小的问题,而这道题并不是,这道题要做的是维护最大前缀和。
首先按照y排序并且离散化每个车站的y坐标,然后再按照x排序,使用树状数组维护最大前缀和即可(当然线段树应该也是可以的,只不过会比树状数组麻烦一点)。注意这里的树状数组不是维护的前缀和,而是维护前缀和的最大值。所以update操作和query操作里并不是求和,而是取最大值。


代码

#include <bits/stdc++.h>
using namespace std;
int get_num(){
    int num = 0;
    char c;
    bool flag = false;
    while((c = getchar()) == ' ' || c == '\r' || c == '\n');
    if(c == '-')
        flag = true;
    else num = c - '0';
    while(isdigit(c = getchar()))
        num = num * 10 + c - '0';
    return (flag ? -1 : 1) * num;
}
const int maxn = 1e5+5;
struct point{
    int x,y,k;
}p[maxn];
bool cmp1(point a,point b){
    return a.y < b.y;
}
bool cmp2(point a,point b){
    if(a.x == b.x)return a.y < b.y;
    return a.x < b.x;
}
int lowbit(int x){
    return x & (-x);
}
int c[maxn];
int n,m,k,cnt;
void update(int x,int d){
    while(x <= 
 2017-01-18 08:56:15 |  0 Comments  |  CDQ分治 树状数组

bzoj 2683 简单题【CDQ分治+树状数组】

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 参数限制 内容
1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A
2 x1 y1 x2 y2 1<=x1<= x2<=N1<=y1<= y2<=N 输出x1 y1 x2 y2这个矩形内的数字和
3 无 终止程序

Input

输入文件第一行一个正整数N。

接下来每行一个操作。

Output

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

Sample Input

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

Sample Output

3
5

HINT

1<=N<=500000,操作数不超过200000个,内存限制20M。

对于100%的数据,操作1中的A不超过2000。

题解

首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用。

首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响。

我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这里的树状数组是需要清的,也就是每次cdq都是采用不同的树状数组。

另:这题神坑,数组开小不是RE而是WA

数组范围是要开到200000*4的,因为对于每个1操作,是一个操作,而2操作根据容斥原理,是4个操作。所以复杂度大概是多少呢O(nlog2(n))cdq+树状数组。n<=800000

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int get_num(){
    int num = 0;
    char c;
    bool flag = false;
    while((c = getchar()) == ' ' || c == '\r' || c == '\n');
    if(c == '-')
      
Title - Artist
0:00