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

HDU 1166 敌兵布阵

单调更新区间查询和

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 1754 I Hate It

单点更新区间查询最值

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

POJ 3468 A Simple Problem with Integers

区间更新区间求和。

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

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 <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

hdu 1698 Just a Hook

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

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

ZOJ 1610 Count the Colors

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

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

下面是参照别人A的代码

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

POJ 3264 Balanced Lineup

查询区间最大最小值。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 4027 Can you answer these queries?

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 1540 Tunnel Warfare

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 3794 Assign the task

其实就一个树形转线性

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

#pragma comment(linker, "/STACK:102400000,102400000")
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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];
queue<int>q[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;
}

HDU 4578 Transformation

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

HDU 4614 Vases and Flowers

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

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 4553 约会安排

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

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

POJ 1177 Picture

线段树扫描线矩形周长并

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 1542 Atlantis

线段树扫描线举行面积并

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 1255 覆盖的面积

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

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

详细的看看callen函数。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

HDU 3642 Get The Treasury

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

然后化为2唯来做

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

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;
}

 
时间: 2024-10-03 03:16:35

Kuangbin 带你飞-线段树专题 题解的相关文章

kuangbin带你飞----线段树专题一(基础操作,单点,区间更新和查询)

A 题意:给出q个询问,单点更新和查询 主要是注意模板的书写 #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<

Kuangbin 带你飞-基础计算几何专题 题解

专题基本全都是模版应用.贴一下模版 const double eps = 1e-8; const int INF = 0x3f3f3f3f; int sgn(double x) { if (fabs(x) < eps) return 0; if (x < 0) return -1; return 1; } struct Point { double x,y; Point(){} Point(double tx,double ty) { x = tx; y = ty; } Point opera

[kuangbin带你飞]之&#39;最小生成树 &#39;专题(未完成)

带飞网址: https://vjudge.net/article/187 专题六: POJ 1251 Jungle RoadsPOJ 1287 NetworkingPOJ 2031 Building a Space StationPOJ 2421 Constructing RoadsZOJ 1586 QS NetworkPOJ 1789 Truck HistoryPOJ 2349 Arctic NetworkPOJ 1751 HighwaysPOJ 1258 Agri-NetPOJ 3026 B

vj线段树专题

vj线段树专题题解 单点更新模板 void build(int x,int l,int r){//sum[x]控制l-r区域 if(l==r){Sum[x]=num[l];return ;} int mid=l+((r-l)>>1); build(x<<1,l,mid); build(x<<1|1,mid+1,r); Sum[x]=Sum[x<<1]+Sum[x<<1|1]; } void add(int a,int b,int l,int r,

[kuangbin]带你飞之&#39;线段树&#39;专题(未完成)

// 带飞网址 https://vjudge.net/article/187 专题七 线段树 HDU 1166 敌兵布阵HDU 1754 I Hate It√ POJ 3468 A Simple Problem with IntegersPOJ 2528 Mayor's postersHDU 1698 Just a HookZOJ 1610 Count the ColorsPOJ 3264 Balanced LineupHDU 4027 Can you answer these queries?

kuangbin带你飞专题一 简单搜索 题解

目录 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题一 简单搜索 总结:用时2天半终于把这个专题刷完了 对于最基础的dfs bfs 路径打印 状态转移也有了一点自己些微的理解 其实2天半可以压缩到1天半的 主要是自己太懒了...慢慢加油刷bin神的专题呀 从大二下学期开始学算法 一开始就知道这个专题 一开始对于这个专题里的所有问题感觉都好难啊..就直接放弃了 看lrj的书 现在看到这个专题还挺唏嘘的吧 突然觉得思维和想法也不是很难 果然是那个时候心不静&还是储量不够吗

「kuangbin带你飞」专题十八 后缀数组

layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kuangbin - 字符串 - 后缀数组 传送门 倍增法 struct DA{ bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } int t1[maxn],t2[maxn],c[maxn]; int r

「kuangbin带你飞」专题二十二 区间DP

layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - kuangbin - 区间DP - 动态规划 传送门 B.LightOJ - 1422 Halloween Costumes 题意 按顺序参加舞会,参加一个舞会要穿一种衣服,可以在参加完一个舞会后套上另一个衣服再去参加舞会,也可以在参加一个舞会的时候把外面的衣服脱了,脱到合适的衣服,但是脱掉的衣服不能再穿,参加完

「kuangbin带你飞」专题二十 斜率DP

layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 - 斜率DP 传送门 A.HDU - 3507 Print Article 题意 就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 题解 概率DP的入门题,把我搞得要死要活的. 首先dp[i]表示输出前i