Kuangbin 带你飞-线段树专题 题解

HDU 1166 敌兵布阵

单调更新区间查询和

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 50010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int sum;
}tree[MAXN * 4];
int src[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    if (l == r)
    {
        tree[id].sum = src[l];
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

void update(int id,int pos,int val)
{
    if (tree[id].l == pos && tree[id].r == pos)
    {
        tree[id].sum += val;
        return;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos <= mid) update(id * 2,pos,val);
    else update(id * 2 + 1,pos,val);
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

int query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].sum;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return query(id * 2 + 1,l,r);
    else if (r <= mid) return query(id * 2,l,r);
    else
    {
        return query(id * 2 ,l,mid) + query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        for (int i = 1 ; i <= N ; i++) scanf("%d",&src[i]);
        build(1,1,N);
        printf("Case %d:\n",kase++);
        char op[10];
        while(scanf("%s",op) != EOF)
        {
            if (op[0] == 'E') break;
            if (op[0] == 'Q')
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d\n",query(1,l,r));
            }
            if (op[0] == 'A')
            {
                int x,val;
                scanf("%d%d",&x,&val);
                update(1,x,val);
            }
            if(op[0] == 'S')
            {
                int x,val;
                scanf("%d%d",&x,&val);
                update(1,x,-val);
            }
        }
    }
    return 0;
}
View Code

HDU 1754 I Hate It

单点更新区间查询最值

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 200010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int val;
}tree[MAXN * 4];
int src[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    if (l == r)
    {
        tree[id].val = src[l];
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
    tree[id].val = max(tree[id * 2].val,tree[id * 2 + 1].val);
}

void update(int id,int pos,int val)
{
    if (tree[id].l == pos && tree[id].r == pos)
    {
        tree[id].val = val;
        return;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos <= mid) update(id * 2,pos,val);
    else update(id * 2 + 1,pos,val);
    tree[id].val = max(tree[id * 2].val,tree[id * 2 + 1].val);
}

int query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].val;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return query(id * 2 + 1,l,r);
    else if (r <= mid) return query(id * 2,l,r);
    else
    {
        return max(query(id * 2,l,mid) ,query(id * 2 + 1,mid + 1,r));
    }
}

int main()
{
    int N,Q;
    while (scanf("%d%d",&N,&Q) != EOF)
    {
        for (int i = 1 ; i <= N; i++) scanf("%d",&src[i]);
        build(1,1,N);
        while (Q--)
        {
            char op[5];
            scanf("%s",op);
            if (op[0] == 'Q')
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d\n",query(1,l,r));
            }
            else
            {
                int x,val;
                scanf("%d%d",&x,&val);
                update(1,x,val);
            }
        }
    }
    return 0;
}
View Code

POJ 3468 A Simple Problem with Integers

区间更新区间求和。

这里就要涉及到懒操作。注意的是lazy被更新的区间一定是当前的区间和已经更新完

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    LL lazy,sum;
}tree[MAXN * 4];
LL src[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lazy = 0;
    if (l == r)
    {
        tree[id].sum = src[l];
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid +1,r);
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

void push_down(int id)
{
    if (tree[id].lazy == 0) return;
    tree[id * 2].sum += (tree[id * 2].r - tree[id * 2].l + 1) * tree[id].lazy;
    tree[id * 2].lazy += tree[id].lazy;
    tree[id * 2 + 1].sum += (tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1) * tree[id].lazy;
    tree[id * 2 + 1].lazy += tree[id].lazy;
    tree[id].lazy = 0;
}


void update(int id,int l,int r,LL val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].lazy += val;
        tree[id].sum += val * (r - l + 1);
        return;
    }
    push_down(id);
    int mid = (tree[id].r + tree[id].l) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2 ,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

LL query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].sum;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return query(id * 2 + 1,l,r);
    else if (r <= mid) return query(id * 2,l,r);
    else
    {
        return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    int N,Q;
    while (scanf("%d%d",&N,&Q) != EOF)
    {
        for (int i = 1 ; i <= N ; i++) scanf("%I64d",&src[i]);
        build(1,1,N);
        char op[10];
        while (Q--)
        {
            scanf("%s",op);
            if (op[0] == 'Q')
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%I64d\n",query(1,l,r));
            }
            else
            {
                int l,r;
                LL val;
                scanf("%d%d%I64d",&l,&r,&val);
                update(1,l,r,val);
            }
        }
    }
    return 0;
}
View Code

POJ 2528 Mayor's posters

区间更新为一个值。然后统计有哪些数出现过

注意需要离散化,且不能随便离散化。

线段树是点操作。这里对长度为1的段进行操作。也就是将一个长度为1的段视作一个点,举个例子

区间为 1-10,1--4,5 -- 10

区间为 1--10,1--4,6-10;

一般的离散化是变成了这样 1离散为1,4离散为2,5离散为3,10离散为4

区间都变成了1-4,1--2,3 -- 4;

显然上面2中答案是不一样的。随便离散是WA的。第一个答案是2,第二个答案是3

那么如何改,方案是如果两个相邻的点差值大于1,那么中间就插入一个点。

那么按照这种离散上面变成了有6个点1,3,4,5,9,10,离散成了1-6,1-3,4-6 答案为2

和第二组问题 变成这样几个点1 3 4 5 6 9 10 离散成了 1--7,1--3,5--7答案为3

代码

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 10010;
map<int,int>mp,res;
struct point
{
    int l,r;
    int idx;
}src[MAXN];
struct node
{
    int l,r;
    int val;
    bool flag;
}tree[MAXN * 16];
int ori[MAXN * 2],newdata[MAXN * 4];

void build(int id,int l,int r)
{
    tree[id].l = newdata[l];
    tree[id].r = newdata[r];
    tree[id].val = -1;
    tree[id].flag = false;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_down(int id)
{
    if (tree[id].flag)
    {
        tree[id * 2].flag = tree[id * 2 + 1].flag = true;
        tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val;
        tree[id].flag = false;
    }
}

void update(int id,int l,int r,int val)
{
    if (r < tree[id].l || l > tree[id].r) return;
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].val = val;
        tree[id].flag = true;
        return;
    }
    push_down(id);
    /*int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2 ,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }*/
    update(id * 2,l,r,val);
    update(id * 2 + 1,l,r,val);
}

void query(int id,int l,int r,int &ret)
{
    if (tree[id].l == tree[id].r)
    {
        if (mp[tree[id].val] == 0 && tree[id].val != -1)
        {
            ret++;
           // printf("%d\n",tree[id].val);
            mp[tree[id].val] = 1;
        }
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    query(id * 2,l,mid,ret);
    query(id * 2 + 1,mid + 1,r,ret);
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        mp.clear();
        res.clear();
        int N;
        scanf("%d",&N);
        int cas = 0;
        for (int i = 1;  i <= N ; i++)
        {
            scanf("%d%d",&src[i].l,&src[i].r);
            src[i].idx = i;
            ori[++cas] = src[i].l;
            ori[++cas] = src[i].r;
        }
        sort(ori + 1,ori + 1 + cas);
        int leap = 0;
        ori[0] = -1;
        for (int i = 1; i <= cas ; i++)
        {
            if (ori[i] != ori[i - 1])
                ori[++leap] = ori[i];
        }
        cas = 0;
        newdata[++cas] = ori[1];
        for (int i = 2 ; i <= leap ; i++)
        {
            if (ori[i] > ori[i - 1] + 1)
            {
                newdata[++cas] = ori[i] - 1;
                newdata[++cas] = ori[i];
            }
            else
            {
                newdata[++cas] = ori[i];
            }
        }
       // printf("%d\n",cas);
        //for (int i = 1 ; i <= cas ; i++)
        //   printf("%d ",newdata[i]); putchar('\n');
        build(1,1,cas);
        for (int i = 1 ; i <= N ; i++)
        {
            update(1,src[i].l,src[i].r,src[i].idx);
        }
        int ret = 0;
        query(1,1,cas,ret);
        printf("%d\n",ret);
    }
    return 0;
}
View Code

hdu 1698 Just a Hook

记得题意是如果一个区间值全部相等,那么权就是这个区间的长度乘以这个值,最开始全都是1

用一个sta记录这个区间是不是所值都相等然后做

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    bool sta;
    int val;
    bool flag;
}tree[MAXN * 4];
int L;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].val = 1;
    tree[id].flag = false;
    tree[id].sta = true;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_down(int id)
{
    if (tree[id].flag)
    {
        tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val;
        tree[id * 2].flag = true;
        tree[id * 2 + 1].flag = true;
        tree[id].flag = false;
        tree[id].sta = true;
        tree[id * 2].sta = true;
        tree[id * 2 + 1].sta = true;
    }
}


void push_up(int id)
{
    if (tree[id * 2].sta == true && tree[id * 2 + 1].sta == true)
    {
        if (tree[id * 2].val == tree[id * 2 + 1].val)
        {
            tree[id].val = tree[id * 2 + 1].val;
            tree[id].sta = true;
        }
        else tree[id].sta = false;
    }
    else tree[id].sta = false;
}

void update(int id,int l,int r,int val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].flag = true;
        tree[id].val = val;
        tree[id].sta = true;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
    push_up(id);
}

int query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        if (tree[id].sta == true)
        {
           // printf("%d %d %d\n",tree[id].l,tree[id].r,tree[id].val);
            return tree[id].val * (tree[id].r - tree[id].l + 1);
        }
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return query(id * 2 + 1,l,r);
    else if (r <= mid) return query(id * 2,l,r);
    else
    {
        return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&L);
        build(1,1,L);
        int Q;
        scanf("%d",&Q);
        while (Q--)
        {
            int l,r,val;
            scanf("%d%d%d",&l,&r,&val);
            update(1,l,r,val);
            //printf("%d %d %d\n",l,r,val);
        }
        printf("Case %d: The total value of the hook is %d.\n",kase++,query(1,1,L));
    }
    return 0;
}
View Code

ZOJ 1610 Count the Colors

只有一次查询。可以直接暴力出来修改后最后每个点的颜色。然后扫一遍

我第一次的做法不知道为何就是老WA。求好心人告知。

下面是参照别人A的代码

结构体的COL表示染了什么颜色

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 8110;
struct node
{
    int l,r,col;
}tree[MAXN * 4];
int cnt[MAXN],col[MAXN],N;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].col = -1;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}


void push_down(int id)
{
    if (tree[id].col != -1)
    {
        tree[id * 2].col = tree[id * 2 + 1].col = tree[id].col;
        tree[id].col = -1;
    }
}

void update(int id,int l,int r,int val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].col = val;
        //printf("%d %d %d\n",tree[id].l,tree[id].r,tree[id].col);
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
}

void query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        //printf("%d\n",tree[id].col);
        if (tree[id].col != -1)
        {
            //printf("%d\n",tree[id].col);
            for (int i = tree[id].l ; i <= tree[id].r ; i++)
                col[i] = tree[id].col;
            return;
        }
    }
    push_down(id);
    if (l == r) return;
    int mid = (tree[id].l + tree[id].r ) / 2;
    if (l > mid) query(id * 2 + 1,l,r);
    else if (r <= mid) query(id * 2,l,r);
    else
    {
        query(id * 2,l,mid);
        query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    while (scanf("%d",&N) != EOF)
    {
        memset(cnt,0,sizeof(cnt));
        build(1,1,8000);
        for (int i = 1 ; i <= N ; i++)
        {
            int l,r,val;
            scanf("%d%d%d",&l,&r,&val);
            update(1,l + 1,r,val);
        }
        memset(col,-1,sizeof(col));
        query(1,1,8000);
        int pre = -1;
        for (int i = 0 ; i <= 8000 ; i++)
        {
            if (col[i] == -1)
            {
                pre = -1;
                continue;
            }
            if (pre != col[i])
            {
                cnt[col[i]]++;
                pre = col[i];
            }
        }
        for (int i = 0 ; i <= 8000 ; i++)
        {
            if (cnt[i]) printf("%d %d\n",i,cnt[i]);
        }
        puts("");
    }
    return 0;
}
View Code

下面是我自己WA的代码在查询中就更新出答案不知道那里有问题

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 8110;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    bool flag,sta;
    int val;
}tree[MAXN * 4];
int N;
int cnt[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].val = -1;
    tree[id].flag = false;
    tree[id].sta = true;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_down(int id)
{
    if (tree[id].flag)
    {
        tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val;
        tree[id * 2].flag = true;
        tree[id * 2 + 1].flag = true;
        tree[id].flag = false;
        tree[id].sta = true;
        tree[id * 2].sta = true;
        tree[id * 2 + 1].sta = true;
    }
}


void push_up(int id)
{
    if (tree[id * 2].sta == true && tree[id * 2 + 1].sta == true)
    {
        if (tree[id * 2].val == tree[id * 2 + 1].val)
        {
            tree[id].val = tree[id * 2 + 1].val;
            tree[id].sta = true;
        }
        else tree[id].sta = false;
    }
    else tree[id].sta = false;
}

void update(int id,int l,int r,int val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].flag = true;
        tree[id].val = val;
        tree[id].sta = true;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
    push_up(id);
}

void query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        if (tree[id].sta == true)
        {
            if (tree[id].val != -1)
            {
                cnt[tree[id].val]++;
              //a  printf("%d\n",tree[id].val);
            }
            return;
        }
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) query(id * 2 + 1,l,r);
    else if (r <= mid) query(id * 2 ,l,r);
    else
    {
        query(id * 2,l,mid);
        query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    //freopen("sample.txt","r",stdin);
    while (scanf("%d",&N) != EOF)
    {
        build(1,1,8010);
        for (int i = 1 ; i <= N ; i++)
        {
            int l,r,val;
            scanf("%d%d%d",&l,&r,&val);
            if (l > r) swap(l,r);
            if (l == r) continue;
            update(1,l + 1,r,val);
        }
        memset(cnt,0,sizeof(cnt));
        query(1,1,8010);
        for (int i = 0 ; i <= 8010 ; i++)
        {
            if (cnt[i] == 0) continue;
            printf("%d %d\n",i,cnt[i]);
        }
        puts("");
    }
    return 0;
}
View Code

POJ 3264 Balanced Lineup

查询区间最大最小值。

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 50010;
struct node
{
    int l,r,MIN,MAX;
}tree[MAXN * 4];
int src[MAXN],N;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    if (l == r)
    {
        tree[id].MIN = tree[id].MAX = src[l];
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
    tree[id].MIN = min(tree[id * 2].MIN,tree[id * 2 + 1].MIN);
    tree[id].MAX = max(tree[id * 2].MAX,tree[id * 2 + 1].MAX);
}

int querymax(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].MAX;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return querymax(id * 2 + 1,l,r);
    else if (r <= mid) return querymax(id * 2,l,r);
    else
    {
        return max(querymax(id * 2,l,mid),querymax(id * 2 + 1,mid + 1,r));
    }
}

int querymin(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].MIN;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return querymin(id * 2 + 1,l,r);
    else if (r <= mid) return querymin(id * 2,l,r);
    else
    {
        return min(querymin(id * 2,l,mid),querymin(id * 2 + 1,mid + 1,r));
    }
}

int main()
{
    int Q;
    while (scanf("%d%d",&N,&Q) != EOF)
    {
        for (int i = 1 ; i <= N ; i++) scanf("%d",&src[i]);
        build(1,1,N);
        while (Q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",querymax(1,l,r) - querymin(1,l,r));
        }
    }
    return 0;
}
View Code

HDU 4027 Can you answer these queries?

每次操作把区间内所有值开跟好向下取整,最大的数最多开7次根到1,所以直接做区间长度等于区间和直接结束

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    LL sum;
    bool flag;
}tree[MAXN * 4];
LL src[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    if (l == r)
    {
        tree[id].sum = src[l];
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

void push_down(int id)
{
    if (tree[id].l == tree[id].r)
    {
        tree[id].sum = (LL)sqrt(1.0 * tree[id].sum);
        return;
    }
    push_down(id * 2);
    push_down(id * 2 + 1);
    tree[id].sum = tree[id * 2 + 1].sum + tree[id * 2].sum;
}

void update(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        if (tree[id].sum == (LL)(tree[id].r - tree[id].l + 1))
            return;
        push_down(id);
        return;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r);
    else if (r <= mid) update(id * 2,l,r);
    else
    {
        update(id * 2,l,mid);
        update(id * 2 + 1,mid + 1,r);
    }
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

LL query(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].sum;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return query(id * 2 + 1,l,r);
    else if (r <= mid) return query(id * 2,l,r);
    else
    {
        return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r);
    }
}

int main()
{
    int N,M,kase = 1;
    while (scanf("%d",&N) != EOF)
    {
        for (int i = 1 ; i <= N ; i++) scanf("%I64d",&src[i]);
        scanf("%d",&M);
        build(1,1,N);
        printf("Case #%d:\n",kase++);
        while (M--)
        {
            int op;
            scanf("%d",&op);
            if (op == 0)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                if (l > r) swap(l,r);
                update(1,l,r);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                if (l > r) swap(l,r);
                printf("%I64d\n",query(1,l,r));
            }
        }
        putchar('\n');
    }
    return 0;
}
View Code

HDU 1540 Tunnel Warfare

维护左连续长,右连续长,最大连续长度

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 50010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int leftlen,rightlen,maxlen;
}tree[MAXN * 4];
stack<int>s;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].leftlen = tree[id].rightlen = tree[id].maxlen = r - l + 1;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}


void push_up(int id)
{
    //leftlen;
    if (tree[id * 2].leftlen == tree[id * 2].r - tree[id * 2].l + 1)
    {
        tree[id].leftlen = tree[id * 2].r - tree[id * 2].l + 1 + tree[id * 2 + 1].leftlen;
    }
    else tree[id].leftlen = tree[id * 2].leftlen;
    //right len
    if (tree[id * 2 + 1].rightlen == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1)
    {
        tree[id].rightlen = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1 + tree[id * 2].rightlen;
    }
    else tree[id].rightlen = tree[id * 2 + 1].rightlen;
    tree[id].maxlen = max(tree[id * 2].maxlen,tree[id * 2 + 1].maxlen);
    tree[id].maxlen = max(tree[id].maxlen,tree[id * 2].rightlen + tree[id * 2 + 1].leftlen);
}

void update(int id,int pos,bool flag)
{
    if (tree[id].l == tree[id].r)
    {
        if (flag)
            tree[id].maxlen = tree[id].leftlen = tree[id].rightlen = 0;
        else
            tree[id].maxlen = tree[id].leftlen = tree[id].rightlen = 1;
        return;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos > mid) update(id * 2 + 1,pos,flag);
    if (pos <= mid) update(id * 2,pos,flag);
    push_up(id);
}

int query(int id,int pos)
{
    if (tree[id].l == tree[id].r ||
            tree[id].maxlen == tree[id].r - tree[id].l + 1)
    {
        return tree[id].maxlen;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos <= mid)//左半段
    {
        int tmppos = tree[id * 2].r - tree[id * 2].rightlen + 1;
        if (pos >= tmppos) return tree[id * 2].rightlen + tree[id * 2 + 1].leftlen;
        else return query(id * 2,pos);
    }
    else
    {
        int tmppos = tree[id * 2 + 1].l + tree[id * 2 + 1].leftlen - 1;
        if (pos <= tmppos) return tree[id * 2 + 1].leftlen + tree[id * 2].rightlen;
        else return query(id * 2 + 1,pos);
    }
}

int main()
{
    //freopen("sample.txt","r",stdin);
    int N,Q;
    while (scanf("%d%d",&N,&Q) != EOF)
    {
        build(1,1,N);
        while (!s.empty()) s.pop();
        while (Q--)
        {
            char op[5];
            scanf("%s",op);
            if (op[0] == 'D')
            {
                int pos;
                scanf("%d",&pos);
                s.push(pos);
                update(1,pos,true);
            }
            if (op[0] == 'Q')
            {
                int pos;
                scanf("%d",&pos);
                printf("%d\n",query(1,pos));
            }
            if (op[0] == 'R')
            {
                if (s.empty()) continue;
                int x = s.top();
                s.pop();
                update(1,x,false);
            }
        }
    }
    return 0;
}
View Code

HDU 3794 Assign the task

其实就一个树形转线性

别的随便做,代码里有排除爆炸手写的树形转线性存一下模版

#pragma comment(linker, "/STACK:102400000,102400000")
#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 50010;
int L[MAXN],R[MAXN];
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int val;
    bool flag;
}tree[MAXN * 4];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].val = -1;
    tree[id].flag = false;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_down(int id)
{
    if (tree[id].flag)
    {
        tree[id * 2].flag = tree[id * 2 + 1].flag = true;
        tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val;
        tree[id].flag = false;
    }
}

void update(int id,int l,int r,int val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        tree[id].flag = true;
        tree[id].val = val;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
}

int query(int id,int pos)
{
    if (tree[id].l == pos && tree[id].r == pos)
    {
        return tree[id].val;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos > mid) return query(id * 2 + 1,pos);
    else return query(id * 2,pos);
}

/*
int Stack[MAXN * 2],top;
int deg[MAXN];
int Index,seq[MAXN];
bool vis[MAXN];
queueq[MAXN];

void get_seq(int st)//这段先序遍历树形转线性我应该是不会的
{
    int pos;
    int idx = 0;
    top = 1;
    Stack[top] = st;
    memset(vis,false,sizeof(vis));
    while (top)
    {
        pos = Stack[top];
        if (!vis[pos])
        {
            vis[pos] = true;
            seq[++idx] = pos;
            L[pos] = idx;
        }
        if (!q[pos].empty())
        {
            Stack[++top] = q[pos].front();
            q[pos].pop();
        }
        else
        {
            R[pos] = idx;
            top--;
        }
    }
}*/
vector<int>q[MAXN];
int Index;
int deg[MAXN];
bool vis[MAXN];


void get_seq(int u)
{
    L[u] = ++Index;
    vis[u] = true;
    for (int i = 0 ; i < (int)q[u].size() ; i++)
    {
        int v = q[u][i];
        if (vis[v]) continue;
        get_seq(v);
    }
    R[u] = Index;
}

int main()
{
    //freopen("sample.txt","r",stdin);
    int T,kase = 1;
    scanf("%d",&T);
    int N,Q;
    while(T--)
    {
        memset(deg,0,sizeof(deg));
        scanf("%d",&N);
        for (int i = 1 ; i <= N ; i++) q[i].clear();
        for (int i = 1 ; i < N ; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            //q[v].push(u);
            q[v].push_back(u);
            deg[u]++;
        }
        build(1,1,N);
        int root = 1;
        for (int i = 1 ; i <= N ; i++)
        {
            if (deg[i] == 0)
            {
                root = i;
                break;
            }
        }
        Index = 0;
        memset(vis,false,sizeof(vis));
        //printf("%d\n",root);
        get_seq(root);
        printf("Case #%d:\n",kase++);
        //for (int i = 1 ; i <= N ; i++) printf("%d %d\n",L[i],R[i]);
        scanf("%d",&Q);
        while (Q--)
        {
            char op[5];
            scanf("%s",op);
            if (op[0] == 'C')
            {
                int x;
                scanf("%d",&x);
                printf("%d\n",query(1,L[x]));
            }
            else
            {
                int x,val;
                scanf("%d%d",&x,&val);
                //printf("%d %d\n",L[x],R[x]);
                update(1,L[x],R[x],val);
            }
        }
    }
    return 0;
}
View Code

HDU 4578 Transformation

这题很吊看这里 http://www.cnblogs.com/Commence/p/4871352.html

HDU 4614 Vases and Flowers

如果某个点可以插花,那么这个点值为1,由于他就是从左往右一直插花,实际上就是二分+区间和的问题。

然后查询一个区间最左边的1和最右边的1

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 50010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int sum,lazy,lft,rht;
}tree[MAXN * 4];
int N,Q;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].sum = r - l + 1;
    tree[id].lft = l;
    tree[id].rht = r;
    tree[id].lazy = 0;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_up(int id)
{
    if (tree[id].l == tree[id].r) return;
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
    if (tree[id * 2].lft != -1) tree[id].lft = tree[id * 2].lft;
    else tree[id].lft = tree[id * 2 + 1].lft;
    if (tree[id * 2 + 1].rht != -1) tree[id].rht = tree[id * 2 + 1].rht;
    else tree[id].rht = tree[id * 2].rht;
}

void push_down(int id)
{
    if (tree[id].l == tree[id].r) return;
    if (tree[id].lazy == 1)
    {
        tree[id * 2].lft = tree[id * 2].l;
        tree[id * 2].rht = tree[id * 2].r;
        tree[id * 2].sum = tree[id * 2].r - tree[id * 2].l + 1;
        tree[id * 2].lazy = 1;
        tree[id * 2 + 1].lft = tree[id * 2 + 1].l;
        tree[id * 2 + 1].rht = tree[id * 2 + 1].r;
        tree[id * 2 + 1].sum = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1;
        tree[id * 2 + 1].lazy = 1;
    }
    if (tree[id].lazy == -1)
    {
        tree[id * 2].lft = -1;
        tree[id * 2].rht = -1;
        tree[id * 2].sum = 0;
        tree[id * 2].lazy = -1;
        tree[id * 2 + 1].lft = -1;
        tree[id * 2 + 1].rht = -1;
        tree[id * 2 + 1].sum = 0;
        tree[id * 2 + 1].lazy = -1;
    }
    tree[id].lazy = 0;
}

void update(int id,int l,int r,int val)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        if (val == 0)
        {
            if (tree[id].sum == 0) return;
            tree[id].sum = 0;
            tree[id].lft = -1;
            tree[id].rht = -1;
            tree[id].lazy = -1;
            return;
        }
        else if (val == 1)
        {
            if (tree[id].r - tree[id].l + 1 == tree[id].sum) return;
            tree[id].sum = tree[id].r - tree[id].l + 1;
            tree[id].lazy = 1;
            tree[id].lft = tree[id].l;
            tree[id].rht = tree[id].r;
            return;
        }
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r,val);
    else if (r <= mid) update(id * 2,l,r,val);
    else
    {
        update(id * 2,l,mid,val);
        update(id * 2 + 1,mid + 1,r,val);
    }
    push_up(id);
}

int getsum(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].sum;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return getsum(id * 2 + 1,l,r);
    else if (r <= mid) return getsum(id * 2,l,r);
    else
    {
        return getsum(id * 2,l,mid) + getsum(id * 2 + 1,mid + 1,r);
    }
}

int queryleft(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].lft;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return queryleft(id * 2 + 1,l,r);
    else if (r <= mid) return queryleft(id * 2,l,r);
    else
    {
        int ret;
        ret = queryleft(id * 2,l,mid);
        if (ret != -1) return ret;
        ret = queryleft(id * 2 + 1,mid + 1,r);
        return ret;
    }
}

int queryright(int id,int l,int r)
{
    if (tree[id].l >= l && tree[id].r <= r)
    {
        return tree[id].rht;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) return queryright(id * 2 + 1,l,r);
    else if (r <= mid) return queryright(id * 2,l,r);
    else
    {
        int ret = queryright(id * 2 + 1,mid + 1,r);
        if (ret != -1) return ret;
        return queryright(id * 2,l,mid);
    }
}

int binseach(int A,int F)
{
    int tmp = getsum(1,A,N);
    if (tmp == 0) return - 1;
    if (tmp < F) return N;
    int l = A,r = N;
    while (l < r)
    {
        int mid = (l + r) / 2;
        int val = getsum(1,A,mid);
        if (val >= F)
        {
            r = mid;
        }
        else l = mid + 1;
    }
    return l;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&N,&Q);
        build(1,1,N);
        while (Q--)
        {
            int op;
            scanf("%d",&op);
            if (op == 1)
            {
                int A,F;
                scanf("%d%d",&A,&F);
                A++;
                int tmp = binseach(A,F);
                if (tmp == -1)
                {
                    puts("Can not put any one.");
                    continue;
                }
                printf("%d %d\n",queryleft(1,A,tmp) - 1,queryright(1,A,tmp) - 1);
                update(1,A,tmp,0);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                l++;
                r++;
                printf("%d\n",r - l + 1 - getsum(1,l,r));
                update(1,l,r,1);
            }
        }
        putchar('\n');
    }
    return 0;
}
View Code

HDU 4553 约会安排

一个优先级问题,优先女神,然后吊斯

女神的询问中先在吊死中找如果吊死中可以满足就同时更新吊死和女神的那个区间值详情看代码

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int lmax,rmax,mmax;
    int lmax1,rmax1,mmax1;
}tree[MAXN * 4];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lmax = tree[id].rmax = tree[id].mmax = r - l + 1;
    tree[id].lmax1 = tree[id].rmax1 = tree[id].mmax1 = r - l + 1;
    if (l == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void push_up(int id)
{
    if (tree[id].r == tree[id].l) return;
    tree[id].lmax = tree[id * 2].lmax;
    if (tree[id * 2].lmax == tree[id * 2].r - tree[id * 2].l + 1)
            tree[id].lmax += tree[id * 2 + 1].lmax;
    tree[id].rmax = tree[id * 2 + 1].rmax;
    if (tree[id * 2 + 1].rmax == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1)
            tree[id].rmax += tree[id * 2].rmax;
    tree[id].mmax = max(tree[id * 2].mmax,tree[id * 2 + 1].mmax);
    tree[id].mmax = max(tree[id].mmax,tree[id * 2].rmax + tree[id * 2 + 1].lmax);

    tree[id].lmax1 = tree[id * 2].lmax1;
    if (tree[id * 2].lmax1 == tree[id * 2].r - tree[id * 2].l + 1)
            tree[id].lmax1 += tree[id * 2 + 1].lmax1;
    tree[id].rmax1 = tree[id * 2 + 1].rmax1;
    if (tree[id * 2 + 1].rmax1 == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1)
            tree[id].rmax1 += tree[id * 2].rmax1;
    tree[id].mmax1 = max(tree[id * 2].mmax1,tree[id * 2 + 1].mmax1);
    tree[id].mmax1 = max(tree[id].mmax1,tree[id * 2].rmax1 + tree[id * 2 + 1].lmax1);
}

void push_down(int id)
{
    if (tree[id].l == tree[id].r) return;
    if (tree[id].mmax == 0)
    {
        tree[id * 2].lmax = tree[id * 2].rmax = tree[id * 2].mmax = 0;
        tree[id * 2 + 1].lmax = tree[id * 2 + 1].rmax = tree[id * 2 + 1].mmax = 0;
    }
    if (tree[id].mmax == tree[id].r - tree[id].l + 1)
    {
        tree[id * 2].lmax = tree[id * 2].rmax = tree[id * 2].mmax = tree[id * 2].r - tree[id * 2].l + 1;
        tree[id * 2 + 1].lmax = tree[id * 2 + 1].rmax = tree[id * 2 + 1].mmax = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1;
    }
    if (tree[id].mmax1 == 0)
    {
        tree[id * 2].lmax1 = tree[id * 2].rmax1 = tree[id * 2].mmax1 = 0;
        tree[id * 2 + 1].lmax1 = tree[id * 2 + 1].rmax1 = tree[id * 2 + 1].mmax1 = 0;
    }
    if (tree[id].mmax1 == tree[id].r - tree[id].l + 1)
    {
        tree[id * 2].lmax1 = tree[id * 2].rmax1 = tree[id * 2].mmax1 = tree[id * 2].r - tree[id * 2].l + 1;
        tree[id * 2 + 1].lmax1 = tree[id * 2 + 1].rmax1 = tree[id * 2 + 1].mmax1 = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1;
    }
}

int query(int id,int x)
{
    if (tree[id].mmax < x) return 0;
    if (tree[id].lmax >= x) return tree[id].l;
    if (tree[id * 2].mmax >= x) return query(id * 2,x);
    if (tree[id * 2].rmax + tree[id * 2 + 1].lmax >= x)
            return tree[id * 2].r- tree[id * 2].rmax + 1;
    return query(id * 2 + 1,x);
}

int query1(int id,int x)
{
    if (tree[id].mmax1 < x) return 0;
    if (tree[id].lmax1 >= x) return tree[id].l;
    if (tree[id * 2].mmax1 >= x) return query1(id * 2,x);
    if (tree[id * 2].rmax1 + tree[id * 2 + 1].lmax1 >= x)
            return tree[id * 2].r- tree[id * 2].rmax1 + 1;
    return query1(id * 2 + 1,x);
}

void update(int id,int l,int r)
{
    if (tree[id].l == l && tree[id].r == r)
    {
        tree[id].mmax = tree[id].lmax = tree[id].rmax = tree[id].r - tree[id].l + 1;
        tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = tree[id].r - tree[id].l + 1;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) update(id * 2 + 1,l,r);
    else if (r <= mid) update(id * 2 ,l,r);
    else
    {
        update(id * 2,l,mid);
        update(id * 2 + 1,mid + 1,r);
    }
    push_up(id);
}

void diors(int id,int l,int r)
{
    if (tree[id].l == l && tree[id].r == r)
    {
        tree[id].mmax = tree[id].lmax = tree[id].rmax = 0;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) diors(id * 2 + 1,l,r);
    else if (r <= mid) diors(id * 2,l,r);
    else
    {
        diors(id * 2,l,mid);
        diors(id * 2 + 1,mid + 1,r);
    }
    push_up(id);
}

void godness(int id,int l,int r)
{
    if (tree[id].l == l && tree[id].r == r)
    {
        tree[id].mmax = tree[id].lmax = tree[id].rmax = 0;
        tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = 0;
        return;
    }
    push_down(id);
    int mid = (tree[id].l + tree[id].r) / 2;
    if (l > mid) godness(id * 2 + 1,l,r);
    else if (r <= mid) godness(id * 2 ,l,r);
    else
    {
        godness(id * 2,l,mid);
        godness(id * 2 + 1,mid + 1,r);
    }
    push_up(id);
}

int main()
{
    //freopen("sample.txt","r",stdin);
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        printf("Case %d:\n",kase++);
        int N,M;
        scanf("%d%d",&N,&M);
        build(1,1,N);
        while (M--)
        {
            char op[5];
            scanf("%s",op);
            if (op[0] == 'D')
            {
                int x;
                scanf("%d",&x);
                int tmp = query(1,x);
                if (tmp == 0) puts("fly with yourself");
                else
                {
                    diors(1,tmp,tmp + x - 1);
                    printf("%d,let's fly\n",tmp);
                }
            }
            else if (op[0] == 'N')
            {
                int x;
                scanf("%d",&x);
                int tmp = query(1,x);
                if (tmp != 0)
                {
                    godness(1,tmp,tmp + x - 1);
                    printf("%d,don't put my gezi\n",tmp);
                    continue;
                }
                tmp = query1(1,x);
                if (tmp != 0)
                {
                    godness(1,tmp,tmp + x - 1);
                    printf("%d,don't put my gezi\n",tmp);
                    continue;
                }
                printf("wait for me\n");
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("I am the hope of chinese chengxuyuan!!\n");
                update(1,l,r);
            }
        }
    }
    return 0;
}
View Code

POJ 1177 Picture

线段树扫描线矩形周长并

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 10010;
struct node
{
    int l,r;
    int cnt;
    int lf,rf;
    int numseg;
    int c;
    bool lcover,rcover;
}tree[MAXN * 4];

struct Line
{
    int y;
    int x1,x2;
    int f;
    friend bool operator < (const Line &a,const Line &b)
    {
        return a.y < b.y;
    }
}line[MAXN];
int x[MAXN],debug;

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lf = x[l];
    tree[id].rf = x[r];
    tree[id].cnt = 0;
    tree[id].numseg = 0;
    tree[id].c = 0;
    tree[id].lcover = tree[id].rcover = false;
    if (l + 1 == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid,r);
}

void callen(int id)
{
    if (tree[id].c > 0)
    {
        tree[id].cnt = tree[id].rf - tree[id].lf;
        tree[id].numseg = 1;
        tree[id].lcover = tree[id].rcover = true;
        return;
    }
    if (tree[id].l + 1 == tree[id].r)
    {
        tree[id].cnt = 0;
        tree[id].numseg = 0;
        tree[id].lcover = tree[id].rcover = false;
    }
    else
    {
       // printf("%d %d %d\n",tree[id].cnt,tree[id * 2].cnt ,tree[id * 2 + 1].cnt);
       // printf("%d %d %d %d\n",tree[id * 2].l,tree[id * 2].r,tree[id * 2 + 1].l,tree[id * 2 + 1].r);
        tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt;
        tree[id].lcover = tree[id * 2].lcover;
        tree[id].rcover = tree[id * 2 + 1].rcover;
        tree[id].numseg = tree[id * 2].numseg + tree[id * 2 + 1].numseg;
        if (tree[id * 2].rcover && tree[id * 2 + 1].lcover) tree[id].numseg--;
    }
}

void update(int id,Line e)
{
    if (tree[id].lf == e.x1 && tree[id].rf == e.x2)
    {
        tree[id].c += e.f;
       // printf("%d %d %d %d %d %d %d\n",debug,tree[id].lf,tree[id].rf,tree[id].cnt,tree[id].c,tree[id].l,tree[id].r);
        callen(id);
        return;
    }
    if (e.x2 <= tree[id * 2].rf) update(id * 2,e);
    else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e);
    else
    {
        Line tmp = e;
        tmp.x2 = tree[id * 2].rf;
        update(id * 2,tmp);
        tmp = e;
        tmp.x1 = tree[id * 2 + 1].lf;
        update(id * 2 + 1,tmp);
    }
    callen(id);
}

int main()
{
    int n;
    while (scanf("%d",&n) != EOF)
    {
        int cas = 0;
        int x1,x2,y1,y2;
        debug = 0;
        for (int i = 0 ; i < n ; i++)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y1;
            line[cas].f = 1;
            x[cas] = x1;
            cas++;
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y2;
            line[cas].f = -1;
            x[cas] = x2;
            cas++;
        }
        sort(line,line + cas);
        sort(x,x + cas);
        int num = unique(x,x + cas) - x;
        build(1,0,num - 1);
        int ret = 0,last = 0;
        for (int i = 0 ; i < cas - 1 ; i++)
        {
            debug++;
            update(1,line[i]);
            ret += tree[1].numseg * 2 * (line[i + 1].y - line[i].y);
            ret += abs(tree[1].cnt - last);
           // printf("%d %d %d %d\n",line[i].x1,line[i].x2,line[i].y,tree[1].cnt);
           // printf("%d\n\n",ret);
            last = tree[1].cnt;
        }
        update(1,line[cas - 1]);
        ret += abs(tree[1].cnt - last);
        printf("%d\n",ret);
    }
    return 0;
}
View Code

HDU 1542 Atlantis

线段树扫描线举行面积并

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 210;
const int INF = 0x3f3f3f3f;
int N;

struct node
{
    int l,r;
    double lf,rf;
    int c;
    double cnt;
}tree[MAXN * 4];

struct Line
{
    double x1,x2;
    double y;
    int f;
    friend bool operator < (const Line &a,const Line &b)
    {
        return a.y < b.y;
    }
}line[MAXN];
double x[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lf = x[l];
    tree[id].rf = x[r];
    tree[id].c = 0;
    tree[id].cnt = 0;
    if (l + 1 == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid,r);
}

void callen(int id)
{
    if (tree[id].c > 0)
    {
        tree[id].cnt = tree[id].rf - tree[id].lf;
        return;
    }
    if (tree[id].l + 1 == tree[id].r)
    {
        tree[id].cnt = 0;
    }
    else
        tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt;
}

void update(int id,Line e)
{
    if (tree[id].lf == e.x1 && tree[id].rf == e.x2)
    {
        tree[id].c += e.f;
        callen(id);
        return;
    }
    if (tree[id * 2].rf >= e.x2) update(id * 2,e);
    else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e);
    else
    {
        Line tmp = e;
        tmp.x2 = tree[id * 2].rf;
        update(id * 2,tmp);
        tmp = e;
        tmp.x1 = tree[id * 2 + 1].lf;
        update(id * 2 + 1,tmp);
    }
    callen(id);
}

int main()
{
    int kase = 1;
    while (scanf("%d",&N) != EOF)
    {
        if (N == 0) break;
        int cas = 0;
        for (int i = 0 ; i < N ; i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y1;
            line[cas].f = 1;
            x[cas++] = x1;
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y2;
            line[cas].f = -1;
            x[cas++] = x2;
        }
        sort(x,x + cas);
        sort(line,line + cas);
        int num = unique(x ,x + cas) - x;
        build(1,0,num - 1);
        double ret = 0;
        update(1,line[0]);
        for (int i = 1 ; i < cas ; i++)
        {
            ret += (line[i].y - line[i - 1].y) * tree[1].cnt;
            update(1,line[i]);
        }
        printf("Test case #%d\n",kase++);
        printf("Total explored area: %.2lf\n\n",ret);
    }
    return 0;
}
View Code

HDU 1255 覆盖的面积

矩形被覆盖2次以上的面积并。这个你要理解下这类问题是怎么解决的

首先c只有的被完全区间的时候会更新,区间被覆盖一次的长度表示什么,并不是一定就只覆盖了一次,

详细的看看callen函数。

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 2010;
struct node
{
    int l,r;
    int c;
    double lf,rf;
    double cnt,more;
}tree[MAXN * 4];

struct Line
{
    double x1,x2;
    double y;
    int f;
    friend bool operator < (const Line &a,const Line &b)
    {
        return a.y < b.y;
    }
}line[MAXN];
double x[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lf = x[l];
    tree[id].rf = x[r];
    tree[id].cnt = tree[id].more = tree[id].c = 0;
    if (l + 1 == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid,r);
}

void callen(int id)
{
    if (tree[id].c >= 2)
    {
        tree[id].more = tree[id].rf - tree[id].lf;
        return;
    }
    if (tree[id].c == 1)
    {
        tree[id].cnt = tree[id].rf - tree[id].lf;
        if (tree[id].l + 1 == tree[id].r) tree[id].more = 0;
        else tree[id].more = tree[id * 2].cnt + tree[id * 2 + 1].cnt;
    }
    else
    {
        if (tree[id].l == tree[id].r - 1)
            tree[id].cnt = tree[id].more = 0;
        else
        {
            tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt;
            tree[id].more = tree[id * 2].more + tree[id * 2 + 1].more;
        }
    }
}

void update(int id,Line e)
{
    if (tree[id].lf == e.x1 && tree[id].rf == e.x2)
    {
        tree[id].c += e.f;
       // printf("%d %d %d %d %d %d %d\n",debug,tree[id].lf,tree[id].rf,tree[id].cnt,tree[id].c,tree[id].l,tree[id].r);
        callen(id);
        return;
    }
    if (e.x2 <= tree[id * 2].rf) update(id * 2,e);
    else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e);
    else
    {
        Line tmp = e;
        tmp.x2 = tree[id * 2].rf;
        update(id * 2,tmp);
        tmp = e;
        tmp.x1 = tree[id * 2 + 1].lf;
        update(id * 2 + 1,tmp);
    }
    callen(id);
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        int cas = 0;
        for (int i = 0 ; i < N ; i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y1;
            line[cas].f = 1;
            x[cas++] = x1;
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].y = y2;
            line[cas].f = -1;
            x[cas++] = x2;
        }
        sort(line,line + cas);
        sort(x,x + cas);
        int num = unique(x,x + cas) - x;
        build(1,0,num - 1);
        update(1,line[0]);
        double ret = 0;
        for (int i = 1 ; i < cas ; i++)
        {
            ret += (line[i].y - line[i - 1].y) * tree[1].more;
            update(1,line[i]);
        }
        printf("%.2lf\n",ret);
    }
    return 0;
}
View Code

HDU 3642 Get The Treasury

线段树扫面线三维体积并,要求三次的内容。由于Z的绝对值小于500,所以可以枚举z

然后化为2唯来做

如何计算callen 中的once,twice,more是关键,理解很关键

#include 
#include <set>
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {
      return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 2010;
const int INF = 0x3f3f3f3f;
struct node
{
    int l,r;
    int lf,rf;
    int once,twice,more;
    int c;
}tree[MAXN * 4];
int x[MAXN],z[MAXN];

struct Line
{
    int y;
    int x1,x2;
    int z1,z2;
    int f;
    friend bool operator < (const Line &a,const Line &b)
    {
        return a.y < b.y;
    }
}line[MAXN],res[MAXN];

void build(int id,int l,int r)
{
    tree[id].l = l;
    tree[id].r = r;
    tree[id].lf = x[l];
    tree[id].rf = x[r];
    tree[id].c = 0;
    tree[id].once = tree[id].twice = tree[id].more = 0;
    if (l + 1 == r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid,r);
}

void callen(int id)
{
    if (tree[id].c >= 3)
    {
        tree[id].more = tree[id].rf - tree[id].lf;
        tree[id].once = tree[id].twice = 0;
        return;
    }
    else if (tree[id].c == 2)
    {
        if (tree[id].l + 1 == tree[id].r)
        {
            tree[id].more = 0;
            tree[id].twice = tree[id].rf - tree[id].lf;
            tree[id].once = 0;
            return;
        }
        else
        {
            tree[id].more = tree[id * 2].once + tree[id * 2].twice + tree[id * 2].more
                        + tree[id * 2 + 1].once + tree[id * 2 + 1].twice + tree[id * 2 + 1].more;
            tree[id].twice = tree[id].rf - tree[id].lf - tree[id].more;
            tree[id].once = 0;
        }
    }
    else if (tree[id].c == 1)
    {
        if (tree[id].l + 1 == tree[id].r)
        {
            tree[id].more = tree[id].twice = 0;
            tree[id].once = tree[id].rf - tree[id].lf;
        }
        else
        {
            tree[id].more = tree[id * 2].more + tree[id * 2].twice
                    + tree[id * 2 + 1].more + tree[id * 2 + 1].twice;
            tree[id].twice = tree[id * 2].once + tree[id * 2 + 1].once;
            tree[id].once = tree[id].rf - tree[id].lf - tree[id].more - tree[id].twice;
        }
    }
    else
    {
        if (tree[id].l == tree[id].r - 1)
        {
            tree[id].more = tree[id].twice = tree[id].once = 0;
        }
        else
        {
            tree[id].more = tree[id * 2].more + tree[id * 2 + 1].more;
            tree[id].twice = tree[id * 2].twice + tree[id * 2 + 1].twice;
            tree[id].once = tree[id * 2].once + tree[id * 2 + 1].once;
        }
    }
}

void update(int id,Line e)
{
    if (tree[id].lf == e.x1 && tree[id].rf == e.x2)
    {
        tree[id].c += e.f;
        callen(id);
        return;
    }
    if (tree[id * 2].rf >= e.x2) update(id * 2,e);
    else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e);
    else
    {
        Line tmp = e;
        tmp.x2 = tree[id * 2].rf;
        update(id * 2,tmp);
        tmp = e;
        tmp.x1 = tree[id * 2 + 1].lf;
        update(id * 2 + 1,tmp);
    }
    callen(id);
}
int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        int cas = 0;
        for (int i = 0 ; i < N ; i++)
        {
            int x1,x2,y1,y2,z1,z2;
            scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].z1 = z1;
            line[cas].z2 = z2;
            line[cas].f = 1;
            line[cas].y = y1;
            x[cas] = x1;
            z[cas++] = z1;

            line[cas].x1 = x1;
            line[cas].x2 = x2;
            line[cas].z1 = z1;
            line[cas].z2 = z2;
            line[cas].f = -1;
            line[cas].y = y2;
            x[cas] = x2;
            z[cas++] = z2;
        }
        sort(line,line + cas);
        sort(x,x + cas);
        sort(z,z + cas);
        int num = unique(x,x + cas) - x;
        build(1,0,num - 1);
        int step = unique(z,z + cas) - z;
        LL ret = 0,area = 0;
        for (int i = 0 ; i < step - 1 ; i++)
        {
            int tot = 0;
            for (int j = 0 ; j < cas ; j++)
            {
                if (line[j].z1 <= z[i] && line[j].z2 > z[i])
                    res[tot++] = line[j];
            }
            area = 0;
            update(1,res[0]);
            for (int j = 1 ; j < tot ; j++)
            {
                area += (LL)(res[j].y - res[j - 1].y) * tree[1].more;
                update(1,res[j]);
            }
            ret += area * (LL)(z[i + 1] - z[i]);
        }
        printf("Case %d: %I64d\n",kase++,ret);
    }
    return 0;
}
View Code

 

离散处理题目。求区间内不同数字的和,和不同数字的个数

Uvalive 5970 An Average Game

离散右端点排序每次标记上一次出现的位置

#include
using namespace std;
const int MAXN = 100100;
#define LL long long
struct node {
    int l,r;
    int idx;
    friend bool operator < (const node &a,const node &b) {
        if (a.r == b.r) return a.l < b.l;
        return a.r < b.r;
    }
}src[MAXN];
int N,Q;
LL A[MAXN];
pairans[MAXN ];

struct treenode {
    int l,r;
    int sum;
}tree[MAXN * 4];

void build(int id,int l,int r) {
    tree[id].l = l;
    tree[id].r = r;
    tree[id].sum = 0;
    if (l >= r) return;
    int mid = (l + r) / 2;
    build(id * 2,l,mid);
    build(id * 2 + 1,mid + 1,r);
}

void update(int id,int pos,bool flag) {
    if (tree[id].l == pos && tree[id].r == pos) {
        if (flag) tree[id].sum = 0;
        else tree[id].sum = 1;
        return;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (pos <= mid) update(id * 2,pos,flag);
    else update(id * 2 + 1,pos,flag);
    tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum;
}

int query(int id,int l,int r) {
    if (tree[id].l >= l && tree[id].r <= r) {
        return tree[id].sum;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if (r <= mid) return query(id * 2,l,r);
    else if (l > mid) return query(id * 2 + 1,l,r);
    else {
        return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r);
    }
}

struct IntervalTree
{
    LL sum[MAXN * 4];
    void build(){memset(sum,0,sizeof(sum));}
    void update(int o,int l,int r,int pos,int val)
    {
        if(l == r)
        {
            sum[o] += val;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)update(o << 1,l,mid,pos,val);
        else update(o<< 1 | 1,mid + 1,r,pos,val);
        sum[o]=sum[o << 1]+sum[o << 1 |1];
    }
    LL query(int o,int l,int r,int q1,int q2)
    {
        if(q1 <= l && r <= q2)return sum[o];
        int mid=(l + r)>>1;
        LL ans=0;
        if(q1 <= mid)ans += query(o << 1,l,mid,q1,q2);
        if(q2 > mid)ans += query(o << 1 | 1,mid + 1,r,q1,q2);
        return  ans;
    }
}Tree;

map<int,int>vis;
int main() {
    int T,kase = 1;
    cin >> T;
    while (T--) {
        cin >> N;
        for (int i = 1 ; i <= N ; i++) cin >> A[i];
        cin >> Q;
        for (int i = 1 ; i <= Q ; i++) { cin >> src[i].l >> src[i].r; if (src[i].l > src[i].r) swap(src[i].l,src[i].r); }
        for (int i = 1 ; i <= Q ; i++) src[i].idx = i;
        vis.clear();
        sort(src + 1,src + 1 + Q);
        build(1,1,N);
        int curpos = 1;
        for (int i = 1 ; i <= Q ; i++) {
            while (curpos <= N && curpos <= src[i].r) {
                if (vis[A[curpos]]) update(1,vis[A[curpos]],true);
                update(1,curpos,false);
                vis[A[curpos]] = curpos;
                curpos++;
            }
            ans[src[i].idx].first = (LL)query(1,src[i].l,src[i].r);
        }

        Tree.build();
        vis.clear();
        int cur = 1;
        for(int i = 1 ; i <= Q ; i++)
        {
            for(; cur <= N && cur <= src[i].r ; cur++)
            {
                if(vis[A[cur]])Tree.update(1,1,N,vis[A[cur]],-A[cur]);
                Tree.update(1,1,N,cur,A[cur]);
                vis[A[cur]] = cur;
            }
            ans[src[i].idx].second = Tree.query(1,1,N,src[i].l,src[i].r);
        }
       // for (int i = 1 ; i <= Q ; i++) cout << ans[i].first << " " << ans[i].second << endl;
        printf("Case %d:\n",kase++);
        for (int i = 1 ; i <= Q ; i++) printf("%.6lf\n",(1.0 * ans[i].second) / (1.0 * ans[i].first));
    }
    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/Commence/p/4877241.html

你可能感兴趣的:(数据结构与算法)