线段树

感觉线段树一直学的不好,从开始学到现在换了很多风格,模板其实不是问题,关键是还是思路吧。

从水题,开始再来一遍。

HDU 1166 敌兵步阵

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define MOD 1000000009
#define N 50000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int p[4*N];
void pushup(int rt)
{
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void build(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        scanf("%d",&p[rt]);
        return ;
    }
    m = (l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int x,int sc,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        p[rt] += sc;
        return ;
    }
    m = (l+r)>>1;
    if(x <= m)
    update(x,sc,lson);
    else
    update(x,sc,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    int m,sum = 0;
    if(l >= L&&r <= R)
    {
        return p[rt];
    }
    m = (l+r)>>1;
    if(L <= m)
    sum += query(L,R,lson);
    if(R > m)
    sum += query(L,R,rson);
    return sum;
}
int main()
{
    int t,cas = 1,a,b,n;
    char str[101];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        build(1,n,1);
        printf("Case %d:\n",cas++);
        for(;;)
        {
            scanf("%s",str);
            if(str[0] == 'E') break;
            if(str[0] == 'Q')
            {
                scanf("%d%d",&a,&b);
                printf("%d\n",query(a,b,1,n,1));
            }
            else if(str[0] == 'A')
            {
                scanf("%d%d",&a,&b);
                update(a,b,1,n,1);
            }
            else
            {
                scanf("%d%d",&a,&b);
                update(a,-b,1,n,1);
            }
        }
    }
    return 0;
}
View Code

HDU 1698 Just a Hook

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 100001
int p[4*N];
int lz[4*N];
void pushup(int rt)
{
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void pushdown(int rt,int m)
{
    if(lz[rt])
    {
        lz[rt<<1] = lz[rt];
        lz[rt<<1|1] = lz[rt];
        p[rt<<1] = lz[rt]*(m-(m>>1));
        p[rt<<1|1] = lz[rt]*(m>>1);
        lz[rt] = 0;
    }
}
void build(int l,int r,int rt)
{
    int m;
    lz[rt] = 0;
    if(l == r)
    {
        p[rt] = 1;
        return ;
    }
    m = (l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    if(L <= l&&R >= r)
    {
        lz[rt] = sc;
        p[rt] = (r-l+1)*sc;
        return ;
    }
    int m = (l+r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    int m,sum = 0;
    if(L <= l&&R >= r)
    {
        return p[rt];
    }
    m = (l+r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
    sum += query(L,R,lson);
    if(R > m)
    sum += query(L,R,rson);
    return sum;
}
int main()
{
    int t,cas = 1,i,n,m,x,y,z;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        build(1,n,1);
        scanf("%d",&m);
        for(i = 1;i <= m;i ++)
        {
            scanf("%d%d%d",&x,&y,&z);
            update(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,n,1,n,1));
    }
    return 0;
}
View Code

 HDU 4614 Vases and Flowers

以前用线段树+二分做的,这次换了一个思路,把插过为0,没插过为1,利用find函数,查找。

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50001
int p[4*N],lz[4*N];
void pushup(int rt)
{
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void pushdown(int rt,int m)
{
    if(lz[rt] != -1)
    {
        lz[rt<<1] = lz[rt];
        lz[rt<<1|1] = lz[rt];
        p[rt<<1] = lz[rt]*(m-(m>>1));
        p[rt<<1|1] = lz[rt]*(m>>1);
        lz[rt] = -1;
    }
}
void build(int l,int r,int rt)
{
    int m;
    lz[rt] = -1;
    if(l == r)
    {
        p[rt] = 1;
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        lz[rt] = sc;
        p[rt] = (r-l+1)*sc;
        return ;
    }
    pushdown(rt,r-l+1);
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    int m,sum = 0;
    if(l >= L&&r <= R)
    {
        return p[rt];
    }
    pushdown(rt,r-l+1);
    m = (l+r)>>1;
    if(L <= m)
    sum += query(L,R,lson);
    if(R > m)
    sum += query(L,R,rson);
    return sum;
}
int find(int x,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        return l;
    }
    pushdown(rt,r-l+1);
    m = (l+r)>>1;
    if(x <= p[rt<<1])
    return find(x,lson);
    else
    return find(x-p[rt<<1],rson);
}
int main()
{
    int t,n,m,i,k,a,b,temp,l,r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        for(i = 1;i <= m;i ++)
        {
            scanf("%d%d%d",&k,&a,&b);
            if(k == 1)
            {
                temp = query(a,n-1,0,n-1,1);
                if(temp == 0)
                {
                    printf("Can not put any one.\n");
                    continue;
                }
                b = min(b,temp);
                if(a == 0)
                temp = 0;
                else
                temp = query(0,a-1,0,n-1,1);
                l = find(temp+1,0,n-1,1);
                r = find(temp+b,0,n-1,1);
                printf("%d %d\n",l,r);
                update(l,r,0,0,n-1,1);
            }
            else
            {
                printf("%d\n",b-a+1-query(a,b,0,n-1,1));
                update(a,b,1,0,n-1,1);
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 ZOJ 1610 Count the Colors

注意这是一段的染色。挺简单的,1Y.

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 8001
int p[4*N],lz[4*N];
int flag[N],o[N];
void pushdown(int rt)
{
    if(lz[rt] != -1)
    {
        lz[rt<<1] = lz[rt];
        lz[rt<<1|1] = lz[rt];
        p[rt<<1] = lz[rt];
        p[rt<<1|1] = lz[rt];
        lz[rt] = -1;
    }
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        lz[rt] = sc;
        p[rt] = sc;
        return ;
    }
    pushdown(rt);
    m = (l + r) >>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
}
void query(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        o[l] = p[rt];
        return ;
    }
    m = (l + r)>>1;
    pushdown(rt);
    query(lson);
    query(rson);
}
int main()
{
    int n,i,x1,x2,c;
    while(scanf("%d",&n)!=EOF)
    {
        memset(flag,0,sizeof(flag));
        memset(o,0,sizeof(o));
        memset(p,-1,sizeof(p));
        memset(lz,-1,sizeof(lz));
        for(i = 0;i < n;i ++)
        {
            scanf("%d%d%d",&x1,&x2,&c);
            if(x1 <= x2-1)
            update(x1,x2-1,c,0,8000,1);
        }
        query(0,8000,1);
        for(i = 1;i <= 8000;i ++)
        {
            if(o[i] != o[i-1])
            {
                if(o[i-1] != -1)
                flag[o[i-1]] ++;
            }
        }
        if(o[8000] != -1)
        flag[o[8000]] ++;
        for(i = 0;i <= 8000;i ++)
        {
            if(flag[i])
            printf("%d %d\n",i,flag[i]);
        }
        printf("\n");
    }
    return 0;
}
View Code

 HDU 4302 Holedox Eating

和4614类似,注意待在原地的时候,方向不变。

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 100001
int p[4*N];
void pushup(int rt)
{
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void update(int x,int sc,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        p[rt] += sc;
        return ;
    }
    m = (l+r)>>1;
    if(x <= m)
    update(x,sc,lson);
    else
    update(x,sc,rson);
    pushup(rt);
}
int find(int x,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        return l;
    }
    m = (l + r) >>1;
    if(x <= p[rt<<1])
    return find(x,lson);
    else
    return find(x-p[rt<<1],rson);
}
int query(int L,int R,int l,int r,int rt)
{
    int m,sum = 0;
    if(l >= L&&r <= R)
    {
        return p[rt];
    }
    m = (l + r)>>1;
    if(L <= m)
    sum += query(L,R,lson);
    if(R > m)
    sum += query(L,R,rson);
    return sum;
}
int Abs(int x)
{
    if(x < 0)
    return -x;
    return x;
}
int main()
{
    int t,n,m,cas = 1,i,k,x,pre,l,r,flag,temp;
    scanf("%d",&t);
    while(t--)
    {
        memset(p,0,sizeof(p));
        int ans = 0;
        scanf("%d%d",&n,&m);
        pre = 0;
        flag = -1;
        for(i = 0;i < m;i ++)
        {
            scanf("%d",&k);
            if(k == 0)
            {
                scanf("%d",&x);
                update(x,1,0,n,1);
            }
            else
            {
                temp = query(0,pre,0,n,1);
                if(p[1] == 0) continue;
                if(temp == 0)
                l = -100000000;
                else
                l = find(temp,0,n,1);
                if(p[1] == temp)
                r = 1000000000;
                else
                r = find(temp+1,0,n,1);
                int te = pre;
                if(l == pre)
                {
                    update(l,-1,0,n,1);
                    continue;
                }
                if(pre - l > r - pre)
                {
                    pre = r;
                    flag = 1;
                    update(r,-1,0,n,1);
                }
                else if(pre - l < r - pre)
                {
                    pre = l;
                    flag = 0;
                    update(l,-1,0,n,1);
                }
                else if(flag)
                {
                    pre = r;
                    update(r,-1,0,n,1);
                }
                else
                {
                    pre = l;
                    update(l,-1,0,n,1);
                }
                ans += Abs(te-pre);
            }
        }
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}
View Code

HDU 1394 Minimum Inversion Number

求逆序数,当移动的时候,我居然毫无想法,看了题解发现如此简单啊....菜啊!!!!

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 10001
int p[4*N];
int flag[N];
int s[N];
void pushup(int rt)
{
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void update(int x,int sc,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        p[rt] = sc;
        return ;
    }
    m = (l + r)>>1;
    if(x <= m)
    update(x,sc,lson);
    else
    update(x,sc,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    int m,sum = 0;
    if(l >= L&&r <= R)
    {
        return p[rt];
    }
    m = (l + r)>>1;
    if(L <= m)
    sum += query(L,R,lson);
    if(R > m)
    sum += query(L,R,rson);
    return sum;
}
int main()
{
    int n,i,sum,ans;
    while(scanf("%d",&n)!=EOF)
    {
        memset(flag,0,sizeof(flag));
        memset(p,0,sizeof(p));
        for(i = 0;i < n;i ++)
        {
            scanf("%d",&s[i]);
            flag[s[i]] = i;
        }
        sum = 0;
        for(i = n-1;i >= 0;i --)
        {
            if(flag[i] != 0)
            {
                sum += query(0,flag[i]-1,0,n-1,1);
            }
            update(flag[i],1,0,n-1,1);
        }
        ans = sum;
        for(i = 0;i < n;i ++)
        {
            sum -= s[i];
            sum += n-1-s[i];
            ans = min(ans,sum);
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 POJ 3264 Balanced Lineup

模板题。

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50001
int minz[4*N],maxz[4*N];
void pushup(int rt)
{
    minz[rt] = min(minz[rt<<1],minz[rt<<1|1]);
    maxz[rt] = max(maxz[rt<<1],maxz[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        scanf("%d",&minz[rt]);
        maxz[rt] = minz[rt];
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
int qmax(int L,int R,int l,int r,int rt)
{
    int m,ans = -1;
    if(l >= L&&r <= R)
    {
        return maxz[rt];
    }
    m = (l + r)>>1;
    if(L <= m)
    ans = max(ans,qmax(L,R,lson));
    if(R > m)
    ans = max(ans,qmax(L,R,rson));
    return ans;
}
int qmin(int L,int R,int l,int r,int rt)
{
    int m,ans = 100000000;
    if(l >= L&&r <= R)
    {
        return minz[rt];
    }
    m = (l + r)>>1;
    if(L <= m)
    ans = min(ans,qmin(L,R,lson));
    if(R > m)
    ans = min(ans,qmin(L,R,rson));
    return ans;
}
int main()
{
    int n,m,i,x,y;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        for(i = 0;i < m;i ++)
        {
            scanf("%d%d",&x,&y);
            printf("%d\n",qmax(x,y,1,n,1)-qmin(x,y,1,n,1));
        }
    }
    return 0;
}
View Code

 ZOJ 3772 Calculate the Function

这题主要是想到矩阵+线段树,就好做了。注意矩阵乘法的顺序会影响最后的结果,倒这把矩阵乘起来。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
#define N 100001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MOD 1000000007
#define LL long long 
struct node
{
    LL s[2][2];
} mat[4*N];
int p[4*N];
int num;
node mul(node a,node b)
{
    node c;
    int i,j,k;
    for(i = 0; i < 2; i ++)
    {
        for(j = 0; j < 2; j ++)
        c.s[i][j] = 0;
    }
    for(i = 0; i < 2; i ++)
    {
        for(j = 0; j < 2; j ++)
        {
            for(k = 0; k < 2; k ++)
            {
                c.s[i][j] += (a.s[i][k] * b.s[k][j])%MOD;
                c.s[i][j] %= MOD;
            }
        }
    }
    return c;
}
void pushup(int rt)
{
    mat[rt] = mul(mat[rt<<1|1],mat[rt<<1]);
}
void build(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        scanf("%d",&mat[rt].s[0][1]);
        p[num++] = mat[rt].s[0][1];
        mat[rt].s[0][0] = 1;
        mat[rt].s[1][1] = 0;
        mat[rt].s[1][0] = 1;
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
node query(int L,int R,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        return mat[rt];
    }
    node sum;
    sum.s[0][0] = sum.s[1][1] = 1;
    sum.s[0][1] = sum.s[1][0] = 0;
    m = (l + r)>>1;
    if(L <= m)
        sum = mul(query(L,R,lson),sum);
    if(R > m)
        sum = mul(query(L,R,rson),sum);
    return sum;
}
int main()
{
    int t,n,m,i,l,r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        num = 1;
        build(1,n,1);
        for(i = 0; i < m; i ++)
        {
            scanf("%d%d",&l,&r);
            if(r == l)
                printf("%d\n",p[l]);
            else if(r == l+1)
                printf("%d\n",p[r]);
            else
            {
                node ans;
                ans = query(l+2,r,1,n,1);
                printf("%d\n",((p[l+1]*ans.s[0][0])%MOD + (p[l]*ans.s[0][1])%MOD)%MOD);
            }
        }
    }
    return 0;
}
View Code

 POJ 3225 Help with Intervals

看的宝哥的题解,这题最难在于异或,用俩延迟标记,解决的。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
#define N 200000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MOD 1000000007
#define LL long long
int lz[4*N],turn[4*N];
int hash[N];
void pushdown(int rt)
{
    if(lz[rt] != -1)
    {
        lz[rt<<1] = lz[rt<<1|1] = lz[rt];
        turn[rt<<1] = turn[rt<<1|1] = turn[rt];
        lz[rt] = -1;
        turn[rt] = 0;
    }
    if(turn[rt])
    {
        if(lz[rt<<1] != -1)
        lz[rt<<1] ^= 1;
        else
        turn[rt<<1] ^= 1;
        if(lz[rt<<1|1] != -1)
        lz[rt<<1|1] ^= 1;
        else
        turn[rt<<1|1] ^= 1;
        turn[rt] = 0;
    }
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        if(sc == 2)
        {
            if(lz[rt] != -1) lz[rt] ^= 1;
            else turn[rt] ^= 1;
        }
        else
        {
            lz[rt] = sc;
            turn[rt] = 0;
        }
        return ;
    }
    pushdown(rt);
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
}
void query(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        if(lz[rt] == 1)
        hash[l] = 1;
        return ;
    }
    pushdown(rt);
    m = (l + r)>>1;
    query(lson);
    query(rson);
}
int main()
{
    char le,ri;
    char ch[10];
    //freopen("a.txt","r",stdin);
    int l,r,n,i;
    n = 65537*2;
    while(scanf("%s%*c%c%d,%d%c%*c",ch,&le,&l,&r,&ri)!=EOF)
    {
        if(le == '(')
           l = l*2 + 1;
        else
           l = l*2;
        if(ri == ')')
           r = r*2 - 1;
        else
           r = r*2;
        if(ch[0] == 'U')
        {
            update(l,r,1,0,n,1);
        }
        else if(ch[0] == 'I')
        {
            if(l-1 >= 0)
            update(0,l-1,0,0,n,1);
            update(r+1,n,0,0,n,1);
        }
        else if(ch[0] == 'D')
        {
            update(l,r,0,0,n,1);
        }
        else if(ch[0] == 'C')
        {
            if(l-1 >= 0)
            update(0,l-1,0,0,n,1);
            update(r+1,n,0,0,n,1);
            update(l,r,2,0,n,1);
        }
        else
        {
            update(l,r,2,0,n,1);
        }
    }
    query(0,n,1);
    int flag = 0;
    l = r = -1;
    for(i = 0;i <= n;i ++)
    {
        if(hash[i])
        {
            if(l == -1) l = i;
            r = i;
        }
        else
        {
            if(l != -1)
            {
                if(flag) printf(" ");
                flag = 1;
                if(l%2)
                printf("(%d,",l/2);
                else
                printf("[%d,",l/2);
                if(r%2)
                printf("%d)",(r+1)/2);
                else
                printf("%d]",r/2);
                l = -1;
            }
        }
    }
    if(flag == 0) printf("empty set");
    printf("\n");
    return 0;
}
View Code

 HDU 4747 Mex 

挺好的一个题,不过貌似和我木啥关系。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 300001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MOD 1000000007
#define LL __int64
int p[N];
int s[N];
LL sum[4*N];
int maxz[4*N];
LL lz[4*N];
int flag[N];
int o[2*N];
void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    maxz[rt] = max(maxz[rt<<1],maxz[rt<<1|1]);
}
void pushdown(int rt,int m)
{
    if(lz[rt] != -1)
    {
        lz[rt<<1] = lz[rt<<1|1] = lz[rt];
        sum[rt<<1] = lz[rt]*(m-(m>>1));
        sum[rt<<1|1] = lz[rt]*(m>>1);
        maxz[rt<<1] = maxz[rt<<1|1] = lz[rt];
        lz[rt] = -1;
    }
}
void build(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        sum[rt] = s[l];
        maxz[rt] = s[l];
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        lz[rt] = sc;
        sum[rt] = sc*(r-l+1);
        maxz[rt] = sc;
        return ;
    }
    pushdown(rt,r-l+1);
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
    pushup(rt);
}
int find(int x,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        if(sum[rt] > x)
        return l;
        else
        return l+1;
    }
    pushdown(rt,r-l+1);
    m = (l + r)>>1;
    if(x < maxz[rt<<1])
    return find(x,lson);
    else
    return find(x,rson);
}
LL query(int L,int R,int l,int r,int rt)
{
    LL ans = 0;
    if(l >= L&&r <= R)
    {
        return sum[rt];
    }
    int m;
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
    ans += query(L,R,lson);
    if(R > m)
    ans += query(L,R,rson);
    return ans;
}
int main()
{
    int i,n,temp,l,r;
    LL ans;
    while(scanf("%d",&n)!=EOF)
    {
        if(n == 0) break;
        memset(o,0,sizeof(o));
        memset(lz,-1,sizeof(lz));
        memset(sum,0,sizeof(sum));
        for(i = 1;i <= n;i ++)
        {
            scanf("%d",&p[i]);
        }
        map<int,int> mp;
        for(i = n;i >= 1;i --)
        {
            if(mp.find(p[i]) != mp.end())
            flag[i] = mp[p[i]];
            else
            flag[i] = n + 1;
            mp[p[i]] = i;
        }
        temp = 0;
        ans = 0;
        for(i = 1;i <= n;i ++)
        {
            if(p[i] < 2*N)
            o[p[i]] = 1;
            while(o[temp]) temp ++;
            s[i] = temp;
            ans += temp;
        }
        build(1,n,1);
        for(i = 1;i <= n;i ++)
        {
            update(1,i,0,1,n,1);
            l = find(p[i],1,n,1);
            r = flag[i] - 1;
            if(l <= r)
            update(l,r,p[i],1,n,1);
            ans += query(1,n,1,n,1);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 HDU 4027 Can you answer these queries?

想想,就会发现一个性质...

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MOD 10007
#define LL __int64
LL sum[4*N];
void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        scanf("%I64d",&sum[rt]);
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
    int m;
    if(sum[rt] == r-l+1)
    {
        return ;
    }
    if(l == r)
    {
        sum[rt] = sqrt(sum[rt]*1.0);
        return ;
    }
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,lson);
    if(R > m)
    update(L,R,rson);
    pushup(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
    int m;
    LL ans = 0;
    if(l >= L&&r <= R)
    {
        return sum[rt];
    }
    m = (l + r)>>1;
    if(L <= m)
    ans += query(L,R,lson);
    if(R > m)
    ans += query(L,R,rson);
    return ans;
}
int main()
{
    int n,m,i,k,cas = 1,a,b;
    while(scanf("%d",&n)!=EOF)
    {
       build(1,n,1);
       scanf("%d",&m);
       printf("Case #%d:\n",cas++);
       for(i = 0;i < m;i ++)
       {
           scanf("%d%d%d",&k,&a,&b);
           if(a > b) swap(a,b);
           if(k == 0)
           {
               update(a,b,1,n,1);
           }
           else
           {
               printf("%I64d\n",query(a,b,1,n,1));
           }
       }
       printf("\n");
    }
    return 0;
}
View Code

 HDU 4578 Transformation

非常麻烦的一个题,两个lz的经典题目,各种卡常数。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 200001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MOD 10007
#define LL __int64
int mul[4*N];
int add[4*N];
int sum[3][4*N];
inline int input()
{
    int r=0;
    char c;
    c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') r=r*10+c-'0',c=getchar();
    return r;
}
void pushup(int rt)
{
    int i;
    for(i = 0; i < 3; i ++)
        sum[i][rt] = (sum[i][rt<<1] + sum[i][rt<<1|1])%MOD;
}
void fun(int rt,int tmul,int tadd,int len)
{
    int i,ans = 0,temp;
    int pa[4],pm[4];
    pa[0] = pm[0] = 1;
    for(i = 1;i < 4;i ++)
    {
        pa[i] = (pa[i-1]*tadd)%MOD;
        pm[i] = (pm[i-1]*tmul)%MOD;
    }
    for(i = 0; i < 3; i ++)
    {
        if(i == 0) temp = 1;
        else temp = 3;
        ans += ((((temp*pa[i])%MOD*pm[3-i])%MOD)*sum[2-i][rt])%MOD;
        ans %= MOD;
    }
    sum[2][rt] = (ans + len*pa[3]%MOD)%MOD;
    sum[1][rt] = (pm[2]*sum[1][rt])%MOD + (((2*tmul*tadd)%MOD)*sum[0][rt])%MOD + (len*pa[2])%MOD;
    sum[1][rt] %= MOD;
    sum[0][rt] = (tmul*sum[0][rt])%MOD + (len*tadd)%MOD;
    sum[0][rt] %= MOD;
}
void pushdown(int rt,int m)
{
    if(mul[rt] != 1)
    {
        mul[rt<<1] = (mul[rt<<1]*mul[rt])%MOD;
        mul[rt<<1|1] = (mul[rt<<1|1]*mul[rt])%MOD;
        add[rt<<1] = (add[rt<<1]*mul[rt])%MOD;
        add[rt<<1|1] = (add[rt<<1|1]*mul[rt])%MOD;
        fun(rt<<1,mul[rt],0,m-(m>>1));
        fun(rt<<1|1,mul[rt],0,m>>1);
        mul[rt] = 1;
    }
    if(add[rt] != 0)
    {
        add[rt<<1] = (add[rt<<1]+add[rt])%MOD;
        add[rt<<1|1] = (add[rt<<1|1]+add[rt])%MOD;
        fun(rt<<1,1,add[rt],m-(m>>1));
        fun(rt<<1|1,1,add[rt],m>>1);
        add[rt] = 0;
    }
}
void build(int l,int r,int rt)
{
    int m,i;
    add[rt] = 0;
    mul[rt] = 1;
    if(l == r)
    {
        for(i = 0;i < 3;i ++)
        sum[i][rt] = 0;
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int L,int R,int tmul,int tadd,int l,int r,int rt)
{
    int m,len;
    if(l >= L&&r <= R)
    {
        add[rt] = (tmul*add[rt] + tadd)%MOD;
        mul[rt] = (tmul*mul[rt])%MOD;
        len = (r-l+1);
        fun(rt,tmul,tadd,len);
        return ;
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
        update(L,R,tmul,tadd,lson);
    if(R > m)
        update(L,R,tmul,tadd,rson);
    pushup(rt);
}
int query(int L,int R,int sc,int l,int r,int rt)
{
    int m,ans = 0;
    if(l >= L&&r <= R)
    {
        return sum[sc][rt];
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
        ans = (ans + query(L,R,sc,lson))%MOD;
    if(R > m)
        ans = (ans + query(L,R,sc,rson))%MOD;
    return ans;
}
int main()
{
    int n,m,i,k,x,y,c;
    while(1)
    {
        n = input();
        m = input();
        if(n == 0&&m == 0)
            break;
        build(1,n,1);
        for(i = 0; i < m; i ++)
        {
            k = input();
            x = input();
            y = input();
            c = input();
            if(k == 1)
            {
                update(x,y,1,c,1,n,1);
            }
            else if(k == 2)
            {
                update(x,y,c,0,1,n,1);
            }
            else if(k == 3)
            {
                update(x,y,0,c,1,n,1);
            }
            else
            {
                printf("%d\n",query(x,y,c-1,1,n,1));
            }
        }
    }
    return 0;
}
View Code

 HDU 4553 约会安排

本来是应该1Y的题目,结果一个i写成了rt,让我一直RE,我盲cha了半天,没检查出错...哎呀,我不能忍啊....

这题思路就是标记最大连续的,左边,右边,延迟。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 101000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int lbd[2][4*N],rbd[2][4*N];
int maxz[2][4*N],lz[2][4*N];
void pushup(int i,int rt,int m)
{
    maxz[i][rt] = max(maxz[i][rt<<1],maxz[i][rt<<1|1]);
    maxz[i][rt] = max(maxz[i][rt],rbd[i][rt<<1] + lbd[i][rt<<1|1]);
    if(lbd[i][rt<<1] == m - (m>>1))
    lbd[i][rt] =  lbd[i][rt<<1] + lbd[i][rt<<1|1];
    else
    lbd[i][rt] = lbd[i][rt<<1];
    if(rbd[i][rt<<1|1] == m>>1)
    rbd[i][rt] = rbd[i][rt<<1|1] + rbd[i][rt<<1];
    else
    rbd[i][rt] = rbd[i][rt<<1|1];
}
void pushdown(int i,int rt,int m)
{
    if(lz[i][rt] != -1)
    {
        lz[i][rt<<1] = lz[i][rt<<1|1] = lz[i][rt];
        maxz[i][rt<<1] = (m-(m>>1))*lz[i][rt];
        maxz[i][rt<<1|1] = (m>>1)*lz[i][rt];
        lbd[i][rt<<1] = (m-(m>>1))*lz[i][rt];
        lbd[i][rt<<1|1] = (m>>1)*lz[i][rt];
        rbd[i][rt<<1] = (m-(m>>1))*lz[i][rt];
        rbd[i][rt<<1|1] = (m>>1)*lz[i][rt];
        lz[i][rt] = -1;
    }
}
void build(int l,int r,int rt)
{
    int m,i;
    lz[0][rt] = -1;
    lz[1][rt] = -1;
    if(l == r)
    {
        for(i = 0;i < 2;i ++)
        {
            lbd[i][rt] = 1;
            rbd[i][rt] = 1;
            maxz[i][rt] = 1;
        }
        return ;
    }
    m = (l + r)>>1;
    build(lson);
    build(rson);
    for(i = 0;i < 2;i ++)
    pushup(i,rt,r-l+1);
}
void update(int i,int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        maxz[i][rt] = sc*(r-l+1);
        lbd[i][rt] = sc*(r-l+1);
        rbd[i][rt] = sc*(r-l+1);
        lz[i][rt] = sc;
        return ;
    }
    m = (l + r)>>1;
    pushdown(i,rt,r-l+1);
    if(L <= m)
    update(i,L,R,sc,lson);
    if(R > m)
    update(i,L,R,sc,rson);
    pushup(i,rt,r-l+1);
}
int find(int i,int x,int l,int r,int rt)
{
   int m = (l + r)>>1;
   pushdown(i,rt,r-l+1);
   if(maxz[i][rt] < x)
   return -1;
   if(l == r)
   {
       return l;
   }
   if(maxz[i][rt<<1] >= x)
   {
       return find(i,x,lson);
   }
   else if(rbd[i][rt<<1] + lbd[i][rt<<1|1] >= x)
   {
       return m - rbd[i][rt<<1] + 1;
   }
   return find(i,x,rson);
}
int main()
{
    int t,n,m,cas = 1,temp,i,a,b;
    char str[1001];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);
        printf("Case %d:\n",cas++);
        for(i = 0;i < m;i ++)
        {
            scanf("%s",str);
            if(str[0] == 'D')
            {
                scanf("%d",&a);
                temp = find(0,a,1,n,1);
                if(temp > 0)
                {
                    update(0,temp,temp+a-1,0,1,n,1);
                    printf("%d,let's fly\n",temp);
                }
                else
                {
                    printf("fly with yourself\n");
                }
            }
            else if(str[0] == 'N')
            {
                scanf("%d",&a);
                temp = find(0,a,1,n,1);
                if(temp > 0)
                {
                    update(0,temp,temp+a-1,0,1,n,1);
                    update(1,temp,temp+a-1,0,1,n,1);
                    printf("%d,don't put my gezi\n",temp);
                    continue;
                }
                temp = find(1,a,1,n,1);
                if(temp > 0)
                {
                    update(0,temp,temp+a-1,0,1,n,1);
                    update(1,temp,temp+a-1,0,1,n,1);
                    printf("%d,don't put my gezi\n",temp);
                    continue;
                }
                printf("wait for me\n");
            }
            else
            {
                scanf("%d%d",&a,&b);
                update(0,a,b,1,1,n,1);
                update(1,a,b,1,1,n,1);
                printf("I am the hope of chinese chengxuyuan!!\n");
            }
        }
    }
    return 0;
}
View Code

HDU 4288 Coder

耐下心来想想,就应该想出来了。不是延迟,就是标记什么的。难得的1Y。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define LL __int64
#define N 100100
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int que[200001];
LL sum[5][4*N];
int flag[4*N];
int q1[N];
int q2[N];
int bin(int x,int n)
{
    int str,end,mid;
    str = 0;
    end = n;
    while(str <= end)
    {
        mid = (str + end)/2;
        if(que[mid] == x)
        return mid;
        else if(que[mid] > x)
        end = mid - 1;
        else
        str = mid + 1;
    }
    return mid;
}
void pushup(int rt)
{
    int i,x;
    x = flag[rt<<1];
    flag[rt] = (flag[rt<<1] + flag[rt<<1|1]) % 5;
    for(i = 0;i < 5;i ++)
    {
        sum[(i+x)%5][rt] = sum[(i+x)%5][rt<<1] + sum[i][rt<<1|1];
    }
}
void update(int x,int sc,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        flag[rt] += sc;
        if(sc == 1)
        sum[1][rt] = que[x];
        else
        sum[1][rt] = 0;
        return ;
    }
    m = (l + r)>>1;
    if(x <= m)
    update(x,sc,lson);
    else
    update(x,sc,rson);
    pushup(rt);
}
int main()
{
    int n,i,k,m;
    char str[10];
    while(scanf("%d",&n)!=EOF)
    {
        m = 0;
        memset(flag,0,sizeof(flag));
        memset(sum,0,sizeof(sum));
        for(i = 0;i < n;i ++)
        {
            scanf("%s",str);
            if(str[0] == 'a')
            {
                scanf("%d",&q2[i]);
                que[m++] = q2[i];
                q1[i] = 1;
            }
            else if(str[0] == 'd')
            {
                scanf("%d",&q2[i]);
                q1[i] = 2;
            }
            else
            {
                q1[i] = 3;
            }
        }
        sort(que,que+m);
        k = 1;
        for(i = 1;i < m;i ++)
        {
            if(que[i] != que[i-1])
            que[k++] = que[i];
        }
        for(i = 0;i < n;i ++)
        {
            if(q1[i] == 1)
            {
                int pos = bin(q2[i],k-1);
                update(pos,1,0,k-1,1);
            }
            else if(q1[i] == 2)
            {
                int pos = bin(q2[i],k-1);
                update(pos,-1,0,k-1,1);
            }
            else
            {
                printf("%I64d\n",sum[3][1]);
            }
        }
    }
    return 0;
}
View Code

 SGU 311 Ice-cream Tycoon

这题写起来比较麻烦,恰好可以进行一个成段染色,并且不影响sum...sum存价格的和,p存数量的和,单点更新+成段更新+离散化,不离散化会MLE。错的飞起,错了很多次。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
#define LL __int64
#define N 201000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
LL sum[4*N];
LL p[4*N];
int lz[4*N];
LL que[N];
LL q[3][N];
void pushup(int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    p[rt] = p[rt<<1] + p[rt<<1|1];
}
void pushdown(int rt,int m)
{
    if(lz[rt])
    {
        lz[rt<<1] = lz[rt<<1|1] = lz[rt];
        sum[rt<<1] = sum[rt<<1|1] = 0;
        p[rt<<1] = p[rt<<1|1] = 0;
        lz[rt] = 0;
    }
}
void update(int x,int sc,int l,int r,int rt)
{
    int m;
    if(l == r)
    {
        p[rt] += sc;
        sum[rt] += (LL)sc*que[l];
        return ;
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(x <= m)
        update(x,sc,lson);
    else
        update(x,sc,rson);
    pushup(rt);
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        lz[rt] = sc;
        sum[rt] = 0;
        p[rt] = 0;
        return ;
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
        update(L,R,sc,lson);
    if(R > m)
        update(L,R,sc,rson);
    pushup(rt);
}
LL query1(int L,int R,int l,int r,int rt)
{
    int m;
    LL ans = 0;
    if(l >= L&&r <= R)
    {
        return p[rt];
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
        ans += query1(L,R,lson);
    if(R > m)
        ans += query1(L,R,rson);
    return ans;
}
LL query2(int L,int R,int l,int r,int rt)
{
    int m;
    LL ans = 0;
    if(l >= L&&r <= R)
    {
        return sum[rt];
    }
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(L <= m)
        ans += query2(L,R,lson);
    if(R > m)
        ans += query2(L,R,rson);
    return ans;
}
int find(LL x,int l,int r,int rt)
{
    int m;
    m = (l + r)>>1;
    pushdown(rt,r-l+1);
    if(l == r)
    return l;
    if(p[rt<<1] >= x)
        return find(x,lson);
    return find(x-p[rt<<1],rson);
}
int bin(int x,int n)
{
    int str,mid,end;
    str = 1;
    end = n;
    while(str <= end)
    {
        mid = (str + end)/2;
        if(que[mid] == x)
        return mid;
        else if(que[mid] > x)
        end = mid - 1;
        else
        str = mid + 1;
    }
    return mid;
}
int main()
{
    char str[100];
    int n,temp,m,k,i;
    LL num,st,a,b;
    k = 1;
    m = 0;
    while(scanf("%s",str)!=EOF)
    {
        scanf("%I64d%I64d",&a,&b);
        if(str[0] == 'A')
        {
            q[0][m] = 0;
            que[k++] = b;
        }
        else
        q[0][m] = 1;
        q[1][m] = a;
        q[2][m] = b;
        m ++;
    }
    sort(que+1,que+k);
    n = 2;
    for(i = 2;i < k;i ++)
    {
        if(que[i] != que[i-1])
        que[n++] = que[i];
    }
    n --;
    for(i = 0;i < m;i ++)
    {
        if(q[0][i] == 0)
        {
            a = q[1][i];
            b = bin(q[2][i],n);
            update(b,a,1,n,1);
        }
        else
        {
            a = q[1][i];
            b = q[2][i];
            if(p[1] < a)
                printf("UNHAPPY\n");
            else
            {
                temp = find(a,1,n,1);
                num = 0;
                st = 0;
                if(temp-1 >= 1)
                {
                    num = query1(1,temp-1,1,n,1);
                    st = query2(1,temp-1,1,n,1);
                }
                if((a-num)*que[temp] + st > b)
                printf("UNHAPPY\n");
                else
                {
                    if(temp-1 >= 1)
                    update(1,temp-1,1,1,n,1);
                    update(temp,-(a-num),1,n,1);
                    printf("HAPPY\n");
                }
            }
        }
    }
    return 0;
}
View Code

 HDU 1255 覆盖的面积

 做过,同类型的,但是其实并不理解,sum[0]表示只有1个矩形覆盖,sum[1]表示2个以上覆盖。如果cnt[1] = 1,此段sum[1] = 左sum[1] + 右sum[1] + 左sum[0] + 右sum[0]。利用这个就能做出来了。

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define LL long long
#define N 10001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct node
{
    double lx,rx,y;
    int s;
    node(){}
    node(double a,double b,double c,int d):lx(a),rx(b),y(c),s(d){}
    bool operator < (const node &S)const
    {
        return y < S.y;
    }
}mat[N];
double sum[2][4*N];
int cnt[4*N];
double que[N];
int bin(double x,int n)
{
    int str,end,mid;
    str = 0;
    end = n;
    while(str <= end)
    {
        mid = (str + end)/2;
        if(que[mid] == x)
        return mid;
        else if(que[mid] > x)
        end = mid - 1;
        else
        str = mid + 1;
    }
    return mid;
}
void pushup(int rt,int l,int r)
{
    if(cnt[rt] == 1)
    {
        sum[1][rt] = sum[0][rt<<1] + sum[0][rt<<1|1] + sum[1][rt<<1] + sum[1][rt<<1|1];
        sum[0][rt] = que[r+1] - que[l] - sum[1][rt];
    }
    else if(cnt[rt] > 1)
    {
        sum[1][rt] = que[r+1] - que[l];
        sum[0][rt] = 0;
    }
    else if(l == r)
    {
        sum[0][rt] = sum[1][rt] = 0;
    }
    else
    {
        sum[0][rt] = sum[0][rt<<1] + sum[0][rt<<1|1];
        sum[1][rt] = sum[1][rt<<1] + sum[1][rt<<1|1];
    }
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        cnt[rt] += sc;
        pushup(rt,l,r);
        return ;
    }
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
    pushup(rt,l,r);
}
int main()
{
    int t,i,n,m,k,l,r;
    double x1,y1,x2,y2;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        m = 0;
        for(i = 0;i < n;i ++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            que[m] = x1;
            mat[m++] = node(x1,x2,y1,1);
            que[m] = x2;
            mat[m++] = node(x1,x2,y2,-1);
        }
        sort(que,que+m);
        sort(mat,mat+m);
        k = 1;
        for(i = 1;i < m;i ++)
        {
            if(que[i] != que[i-1])
            que[k++] = que[i];
        }
        memset(cnt,0,sizeof(cnt));
        memset(sum,0,sizeof(sum));
        double ans = 0.0;
        for(i = 0;i < m-1;i ++)
        {
            l = bin(mat[i].lx,k-1);
            r = bin(mat[i].rx,k-1)-1;
            if(l <= r)
            update(l,r,mat[i].s,0,k-1,1);
            ans += sum[1][1]*(mat[i+1].y-mat[i].y);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}
View Code

 HDU 3642 Get The Treasury

三维立方体,求三个及以上的体积并,注意int64,wa了几次,思路跟面积并什么的差不多。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define N 3001
#define LL __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct point
{
    int x,y,z;
}p[2001];
LL sum[3][4*N];
int cnt[4*N];
int zi[N];
int que[N];
struct node
{
    int lx,rx,y,s;
    node(){}
    node(int a,int b,int c,int d):lx(a),rx(b),y(c),s(d){}
    bool operator < (const node &S)const
    {
        return y < S.y;
    }
}mat[N];
int bin(int x,int n)
{
    int str,end,mid;
    str = 0;
    end = n;
    while(str <= end)
    {
        mid = (str + end)/2;
        if(que[mid] == x)
        return mid;
        else if(que[mid] > x)
        end = mid - 1;
        else
        str = mid + 1;
    }
    return mid;
}
void pushup(int rt,int l,int r)
{
    int i;
    if(cnt[rt] >= 3)
    {
        sum[2][rt] = que[r+1] - que[l];
        sum[1][rt] = 0;
        sum[0][rt] = 0;
    }
    else if(cnt[rt] == 2)
    {
        sum[2][rt] = 0;
        for(i = 0;i < 3;i ++)
        sum[2][rt] += sum[i][rt<<1] + sum[i][rt<<1|1];
        sum[1][rt] = que[r+1] - que[l] - sum[2][rt];
        sum[0][rt] = 0;
    }
    else if(cnt[rt] == 1)
    {
        sum[2][rt] = sum[2][rt<<1] + sum[2][rt<<1|1] + sum[1][rt<<1] + sum[1][rt<<1|1];
        sum[1][rt] = sum[0][rt<<1] + sum[0][rt<<1|1];
        sum[0][rt] = que[r+1] - que[l] - sum[2][rt] - sum[1][rt];
    }
    else if(l == r)
    {
        sum[0][rt] = sum[1][rt] = sum[2][rt] = 0;
    }
    else
    {
        for(i = 0;i < 3;i ++)
        sum[i][rt] = sum[i][rt<<1] + sum[i][rt<<1|1];
    }
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        cnt[rt] += sc;
        pushup(rt,l,r);
        return ;
    }
    m = (l + r)>>1;
    if(L <= m)
    update(L,R,sc,lson);
    if(R > m)
    update(L,R,sc,rson);
    pushup(rt,l,r);
}
LL fun(int n)
{
    int i,k,l,r;
    LL ans;
    k = 1;
    for(i = 1;i < n;i ++)
    {
        if(que[i] != que[i-1])
        que[k++] = que[i];
    }
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
    ans = 0;
    for(i = 0;i < n-1;i ++)
    {
        l = bin(mat[i].lx,k-1);
        r = bin(mat[i].rx,k-1)-1;
        if(l <= r)
        update(l,r,mat[i].s,0,k-1,1);
        ans += (LL)sum[2][1]*(mat[i+1].y-mat[i].y);
    }
    return ans;
}
int main()
{
    int t,cas = 1,n,i,j,k,num;
    LL ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i = 0;i < 2*n;i ++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
            zi[i] = p[i].z;
        }
        sort(zi,zi+2*n);
        k = 1;
        for(i = 1;i < 2*n;i ++)
        {
            if(zi[i] != zi[i-1])
            zi[k++] = zi[i];
        }
        ans = 0;
        for(i = 0;i < k-1;i ++)
        {
            num = 0;
            for(j = 0;j < n;j ++)
            {
                if(zi[i] >= p[j*2].z&&zi[i] < p[j*2+1].z)
                {
                    que[num] = p[j*2].x;
                    mat[num++] = node(p[j*2].x,p[j*2+1].x,p[j*2].y,1);
                    que[num] = p[j*2+1].x;
                    mat[num++] = node(p[j*2].x,p[j*2+1].x,p[j*2+1].y,-1);
                }
            }
            sort(que,que+num);
            sort(mat,mat+num);
            ans += (LL)fun(num)*(zi[i+1]-zi[i]);
        }
        printf("Case %d: %I64d\n",cas++,ans);
    }
    return 0;
}
View Code

 SGU Kalevich Strikes Back 这个题,很特别。扫描线的时候如果下边发生覆盖,这次的线段肯定比上次的要短,所以每个矩形都有一个pre,pre的矩形-当前矩形的面积就行了,可是我写的一直有问题,看了看别人的+了一个pushup函数就过了,更新那里还是有点问题啊....

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long
#define N 220100
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct node
{
    int lx,rx,y,s,id;
    node() {}
    node(int a,int b,int c,int d,int t):lx(a),rx(b),y(c),s(d),id(t) {}
    bool operator < (const node &S)const
    {
        return y < S.y;
    }
} mat[N];
int lz[4*N];
int que[N];
int pre[N];
int flag[N];
LL ans[N];
int bin(int x,int n)
{
    int str,mid,end;
    str = 0;
    end = n;
    while(str <= end)
    {
        mid = (str + end)/2;
        if(que[mid] == x)
            return mid;
        else if(que[mid] > x)
            end = mid - 1;
        else
            str = mid + 1;
    }
    return mid;
}
void pushdown(int rt)
{
    if(lz[rt])
    {
        lz[rt<<1] = lz[rt<<1|1] = lz[rt];
        lz[rt] = 0;
    }
}
void pushup(int rt)
{
    if(lz[rt<<1] == lz[rt<<1|1]&&lz[rt<<1])
    {
        lz[rt] = lz[rt<<1];
        lz[rt<<1] = lz[rt<<1|1] = 0;
    }
}
void update(int L,int R,int sc,int l,int r,int rt)
{
    int m;
    if(l >= L&&r <= R)
    {
        if(sc < 0)
        {
            lz[rt] = pre[-sc];
        }
        else
        {
            if(flag[sc] == 0&&lz[rt])
            {
                pre[sc] = lz[rt];
                flag[sc] = 1;
                ans[lz[rt]] -= ans[sc];
            }
            lz[rt] = sc;
        }
        return ;
    }
    pushdown(rt);
    m = (l + r) >> 1;
    if(L <= m)
        update(L,R,sc,lson);
    if(R > m)
        update(L,R,sc,rson);
    pushup(rt);
}
int main()
{
    int i,k,n,m,x1,x2,y1,y2,w,h,num;
    scanf("%d",&n);
    m = 0;
    num = 1;
    scanf("%d%d",&w,&h);
    x1 = w;
    y1 = 0;
    x2 = 0;
    y2 = h;
    que[m] = x1;
    ans[num++] = ((LL)x1-x2)*((LL)y2-y1);
    mat[m++] = node(x2,x1,y1,1,num-1);
    que[m] = x2;
    mat[m++] = node(x2,x1,y2,-1,num-1);
    for(i = 0; i < n; i ++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(x2 > x1) swap(x2,x1);
        if(y1 > y2) swap(y1,y2);
        que[m] = x1;
        ans[num++] = ((LL)x1-x2)*((LL)y2-y1);
        mat[m++] = node(x2,x1,y1,1,num-1);
        que[m] = x2;
        mat[m++] = node(x2,x1,y2,-1,num-1);
    }
    sort(que,que+m);
    sort(mat,mat+m);
    k = 1;
    for(i = 1; i < m; i ++)
    {
        if(que[i] != que[i-1])
            que[k++] = que[i];
    }
    memset(lz,0,sizeof(lz));
    memset(pre,0,sizeof(pre));
    int l,r;
    for(i = 0; i < m-1; i ++)
    {
        l = bin(mat[i].lx,k-1);
        r = bin(mat[i].rx,k-1)-1;
        if(l <= r)
        {
            if(mat[i].s > 0)
                update(l,r,mat[i].id,0,k-1,1);
            else
                update(l,r,-mat[i].id,0,k-1,1);
        }
    }
    sort(ans,ans+num);
    for(i = 1; i < num; i ++)
    {
        if(i != 1)
            printf(" ");
        printf("%lld",ans[i]);
    }
    printf("\n");
    return 0;
}
/*
4
7 7
1 1 2 2
1 3 4 4
3 1 4 2
5 1 6 6

*/
View Code

 

 

 

 

 

posted @ 2014-05-22 19:06  Naix_x  阅读(417)  评论(0编辑  收藏  举报