码迷,mamicode.com
首页 > 其他好文 > 详细

20150301模拟赛

时间:2015-03-02 22:24:23      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:

T1

题目大意:一棵支持当前和历史最大值查询的,有区间加、区间覆盖操作的线段树。

思路:考试的时候,只会骗分了(小的数据就暴力,大的就忽略掉历史最大值的查询然后线段树,把操作都看做*a+b的形式,然后。。。)。后来看了正解,也是看了好久才懂。用六个变量:maxn,pmaxn,add,padd,c,pc来保存一个节点的信息。建树、操作、查询都没有特殊的,就是pushdown的时候,真心美(sang)丽(bing),具体的就不在这里写了,直接上code吧。

注意:1)如果有覆盖,就忽略掉区间加;如果有区间加,就尽量放到覆盖的值上;2)要特别注意带p的变量的更新。。。

技术分享
#include<iostream>
#include<cstdio>
#define ri -1<<31
using namespace std;
struct use{
    int maxn,pmaxn,add,padd,c,pc;
}tree[400000];
int a[100001]={0};
char ch;
void updata(int i)
{
    tree[i].maxn=max(tree[i*2].maxn,tree[i*2+1].maxn);
    tree[i].pmaxn=max(tree[i*2].pmaxn,tree[i*2+1].pmaxn);
}
void pushdown(int i)
{
    int j,son;
    for (j=0;j<=1;++j)
    {
        son=i*2+j;
        tree[son].pmaxn=max(tree[son].pmaxn,max(tree[i].pc,tree[son].maxn+tree[i].padd));
        if (tree[son].c==ri)
            tree[son].padd=max(tree[son].padd,tree[son].add+tree[i].padd);
        else tree[son].pc=max(tree[son].pc,tree[son].c+tree[i].padd);
        if (tree[i].add)
        {
            if (tree[son].c!=ri) tree[son].c+=tree[i].add;
            else tree[son].add+=tree[i].add;
            tree[son].maxn+=tree[i].add;
        }
        if (tree[i].c!=ri)
        {
            tree[son].maxn=tree[son].c=tree[i].c;
            tree[son].add=0;
        }
        tree[son].pc=max(tree[son].pc,max(tree[son].c,tree[i].pc));
        tree[son].padd=max(tree[son].padd,tree[son].add);
    }
    tree[i].padd=tree[i].add=0;
    tree[i].pc=tree[i].c=ri;
}
void build(int i,int l,int r)
{
    int mid;
    tree[i].add=tree[i].padd=0;
    tree[i].c=tree[i].pc=ri;
    if (l==r)
    {
        tree[i].maxn=tree[i].pmaxn=a[l];
        return;
    }
    mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    updata(i);
}
int ask(int i,int l,int r,int ll,int rr)
{
    int mid,maxn;
    if (l!=r) pushdown(i);
    if (ll<=l&&r<=rr)
    {
        if (ch==Q) return tree[i].maxn;
        else return tree[i].pmaxn;
    }
    mid=(l+r)/2;maxn=ri;
    if (ll<=mid) maxn=max(maxn,ask(i*2,l,mid,ll,rr));
    if (rr>mid) maxn=max(maxn,ask(i*2+1,mid+1,r,ll,rr));
    return maxn;
}
void work(int i,int l,int r,int ll,int rr,int cc)
{
    int mid;
    if (l!=r) pushdown(i);
    if (ll<=l&&r<=rr)
    {
        if (ch==P)
        {
            tree[i].maxn+=cc;tree[i].add+=cc;tree[i].padd+=cc;
        }
        else
        {
            tree[i].c=tree[i].pc=tree[i].maxn=cc;
        }
        if (tree[i].maxn>tree[i].pmaxn) tree[i].pmaxn=tree[i].maxn;
        return;
    }
    mid=(l+r)/2;
    if (ll<=mid) work(i*2,l,mid,ll,rr,cc);
    if (rr>mid) work(i*2+1,mid+1,r,ll,rr,cc);
    updata(i);
}
int main()
{
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    
    int t,i,j,e,x,y,z;
    scanf("%d",&t);
    for (i=1;i<=t;++i)
        scanf("%d",&a[i]);
    build(1,1,t);
    scanf("%d",&e);
    for (i=1;i<=e;++i)
    {
        while(scanf("%c",&ch)==1)
            if (ch>=A&&ch<=Z) break;
        if (ch==Q||ch==A)
        {
            scanf("%d%d",&x,&y);
            printf("%d\n",ask(1,1,t,x,y));
        }
        else
        {
            scanf("%d%d%d",&x,&y,&z);
            work(1,1,t,x,y,z);
        }
    }
    
    fclose(stdin);
    fclose(stdout);
}
View Code

 

20150301模拟赛

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4309736.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!