线段树&树状数组&扫描线

来源:互联网 发布:报表软件排名 编辑:程序博客网 时间:2024/06/05 02:16
树状数组 :http://blog.csdn.net/int64ago/article/details/7429868
树状数组求最值:http://blog.csdn.net/u010598215/article/details/48206959
线段树:http://www.cnblogs.com/TenosDoIt/p/3453089.html
ZKW线段树 :http://www.cnblogs.com/SinGuLaRiTy2001/p/6591718.html


题目:https://vjudge.net/contest/177556



~i&1
奇数   0   
偶数   1


例题:
hdu 1166 敌兵布阵(线段树&树状数组)
hdu 1754 I Hate It
Poj 3468 A Simple Problem with Integers (区间更新)



题目:
hdu 1166 敌兵布阵(单点更新)
hdu 1754 I Hate It (单点更新)
hdu 2795 Billboard (单点更新)
hdu 1540 Tunnel Warfare (l, r, mx)
Lightoj 1080 Binary Simulation 
Lightoj 1085 All Possible Increasing Subsequences 
hdu 1541 Stars (树状数组)
hdu 1394 Minimum Inversion Number (线段树求逆序数)
CF 272c Dima and Staircase水题(区间更新)
hdu 1698 Just a Hook (区间更新)
Poj 3468 A Simple Problem with Integers(区间更新)
hdu 4553 约会安排 (区间更新)
hdu 4267 A Simple Problem with Integers(区间更新&树状数组写)
Lightoj 1120 Rectangle Union(扫描线)
hdu 1255 覆盖的面积(扫描线)
UESTC 1597 An easy problem C 

http://codeforces.com/contest/612/problem/D(扫描线基础题)
题解:http://blog.csdn.net/qq_34287501/article/details/77248371
//Poj 1151(扫描线)



以上题目题解:http://blog.csdn.net/qq_34287501/article/details/77222119


模板:

//树状数组求最值:void updata(int k){    while(k <= n)    {        dp[k] = a[k];        int lx = k&(-k);        for(int i = 1; i < lx; i <<= 1) dp[k] = max(dp[k], dp[k - i]);        k += k&(-k);    }}int Max(int l, int r){    int ans = 0;    while(r >= l)    {        ans = max(ans, a[r]);        r--;        for(; r - (r&(-r)) >= l; r -= r&(-r)) ans = max(ans, dp[r]);    }    return ans;}//树状数组求和:void add(int k, int x){    while(k <= n)    {        dp[k] += x;        k += k&(-k);    }}int sum(int k){    int ans = 0;    while(k > 0)    {        ans += dp[k];        k -= k&(-k);    }    return ans;}/*   线段树:*///单点更新1:struct node{    int l, r, n;} t[N << 2];void Creat(int l, int r, int i){    t[i].l = l;    t[i].r = r;    if(l == r)    {        scanf("%d", &t[i].n);        return ;    }    int m = (l + r) >> 1;    Creat(l, m, i * 2);    Creat(m + 1, r, i * 2 + 1);    t[i].n = t[i * 2].n + t[i * 2 + 1].n;}void updata(int i, int x, int y){    if(x >= t[i].l && x <= t[i].r)    {        t[i].n += y;        if(x == t[i].l && x == t[i].r) return ;        updata(i * 2, x, y);        updata(i * 2 + 1, x, y);    }}int Find(int i, int l, int r){    if(t[i].l == l && t[i].r == r)        return t[i].n;    int m = (t[i].l + t[i].r) >> 1;    if(m >= r)        return Find(i * 2, l, r);    else if(m + 1 <= l)        return Find(i * 2 + 1, l, r);    else        return Find(i * 2, l, m) + Find(i * 2 + 1, m + 1, r);}//单点更新2.struct node{    int x;} t[N<<2];void Creat(int i, int l, int r){    if(l == r)    {        scanf("%d", &t[i].x);        return ;    }    int mid = (l + r)>>1;    Creat(i*2+1, l, mid);    Creat(i*2+2, mid+1, r);    t[i].x = max(t[i*2+1].x, t[i*2+2].x);}void updata(int i, int l, int r, int x, int y){    if(l == r && l == x)    {        t[i].x = y;        return ;    }    int mid = (l + r)>>1;    if(mid >= x) updata(i*2+1, l, mid, x, y);    else updata(i*2+2, mid+1, r, x, y);    t[i].x = max(t[i*2+1].x, t[i*2+2].x);}int Find(int i, int l, int r, int x, int y){    if(l == x && r == y) return t[i].x;    int mid = (l + r)>>1;    if(mid >= y) return Find(i*2+1, l, mid, x, y);    else if(mid < x) return Find(i*2+2, mid + 1, r, x, y);    return max(Find(i*2+1, l, mid, x, mid), Find(i*2+2, mid+1, r, mid+1, y));}//区间更新.typedef long long LL;using namespace std;const int N = 100009;struct node{    LL x, mark;} t[N<<2];void Creat(int i, int l, int r){    t[i].mark = 0ll;    if(l == r)    {        scanf("%lld", &t[i].x);        return ;    }    int mid = (l + r)>>1;    Creat(i*2, l, mid);    Creat(i*2+1, mid+1, r);    t[i].x = t[i*2].x + t[i*2+1].x;}void pushdown(int i, int l, int r){    if(t[i].mark)    {        int mid = (l + r)>>1;        t[i*2].mark += t[i].mark;        t[i*2+1].mark += t[i].mark;        t[i*2].x += t[i].mark*(mid-l+1);        t[i*2+1].x += t[i].mark*(r-mid);        t[i].mark = 0;    }}void updata(int i, int l, int r, int x, int y, LL z){    if(r < x || y < l) return ;    if(x <= l && r <= y)    {        t[i].mark += z;        t[i].x += z*(r-l+1);        return ;    }    pushdown(i, l, r);    int mid = (l + r)>>1;    updata(i*2, l, mid, x, y, z);    updata(i*2+1, mid+1, r, x, y, z);    t[i].x = t[i*2].x + t[i*2+1].x;}LL Find(int i, int l, int r, int x, int y){    if(r < x || y < l) return 0;    if(x <= l && r <= y) return t[i].x;    pushdown(i, l, r);    int mid = (l + r)>>1;    return Find(i*2, l, mid, x, y) + Find(i*2+1, mid+1, r, x, y);}/*   扫描线:*/struct node{    int x1, x2, y, f;} mp[60009];int x[60009];int f[60009*4], sum[60009*4];void pushup(int i, int l, int r){    if(f[i])    {        sum[i] = x[r+1] - x[l];    }    else if(l == r)    {        sum[i] = 0;    }    else sum[i] = sum[i<<1] + sum[i<<1|1];}void updata(int i, int l, int r, int x, int y, int z){    if(y < l || r < x) return ;    if(x <= l && r <= y)    {        f[i] += z;        pushup(i, l, r);        return ;    }    int mid = (l+r)>>1;    updata(i<<1, l, mid, x, y, z);    updata(i<<1|1, mid+1, r, x, y, z);    pushup(i, l, r);}bool cmp(node a, node b){    if(a.y != b.y) return a.y < b.y;    return a.f > b.f;}int main(){    int t, n, Case = 0;    scanf("%d", &t);    while(t--)    {        memset(sum, 0, sizeof(sum));        memset(f, 0, sizeof(f));        scanf("%d", &n);        int len = 0, x1, y1, x2, y2;        for(int i = 1; i <= n; i++)        {            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);            mp[len] = (node)            {                x1, x2, y1, 1            };            x[len++] = x1;            mp[len] = (node)            {                x1, x2, y2, -1            };            x[len++] = x2;        }        sort(x, x+len);        sort(mp, mp+len, cmp);        int cnt = unique(x, x+len) - x;        int l, r;        LL ans = 0ll;        for(int i = 0; i < len; i++)        {            l = lower_bound(x, x+cnt, mp[i].x1) - x;            r = lower_bound(x, x+cnt, mp[i].x2) - x - 1;            updata(1, 0, cnt - 1, l, r, mp[i].f);            ans += (LL)sum[1] * (mp[i+1].y - mp[i].y);        }        printf("Case %d: %lld\n", ++Case, ans);    }    return 0;}//两次标记扫描线void pushup(int i, int l, int r)  {      if(f[i]) sum1[i] = x[r+1] - x[l];      else if(l == r) sum1[i] = 0;      else sum1[i] = sum1[i<<1] + sum1[i<<1|1];        if(f[i] > 1) sum[i] = x[r+1] - x[l];      else if(l == r) sum[i] = 0;      else if(f[i] == 1) sum[i] = sum1[i<<1] + sum1[i<<1|1];      else sum[i] = sum[i<<1] + sum[i<<1|1];  }