`
kmplayer
  • 浏览: 496938 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

国际大学生程序设计竞赛例题_3.3儿童节快乐

阅读更多
1,题意:
I a b c给区间[a b]加c个糖果.
C a b选出[a b]最多的糖果,并取出.
2,解决:
动态的区间数据维护,可用线段树解决.
3,实现代码:
#include <iostream>
using namespace std;

#define MAX(a,b) ( a>b? a:b )
const int MAXN=100005;

struct Node
{
    int a,b;//左右端点
    int m;//区间最多的糖果数
    int mIndex;//区间最多糖果数的下标
    int r;//区间的糖果数增量
};
Node tree[MAXN*4];

void build(int x,int y,int k)//从位置tree[k]建立线段树
{

    tree[k].a=x;
    tree[k].b=y;
    tree[k].m=0; //初始化为0
    tree[k].mIndex=x;
    tree[k].r=0;
    if(x<y)
    {
        int mid=(x+y)/2;
        build(x,mid,2*k+1);
        build(mid+1,y,2*k+2);
    }

}

//在节点tree[k]上执行操作I x y p
void insert(int x,int y,int p,int k)
{
    if( x<=tree[k].a&&y>=tree[k].b )//x,y完全覆盖了tree[k]的区间
    {
        tree[k].m+=p; //糖果最多数增加
        tree[k].r+=p; //增量
        return;
    }

    int r=tree[k].r;
    tree[2*k+1].r+=r;tree[2*k+1].m+=r;
    tree[2*k+2].r+=r;tree[2*k+2].m+=r;
    tree[k].r=0;//将增量分发给了子区间

    int mid=(tree[k].a+tree[k].b)/2;
    if(x<=mid)//[x y]与左孩子有交集
        insert(x,y,p,2*k+1);
    if(y>=mid+1)//与有孩子有交集
        insert(x,y,p,2*k+2);

    tree[k].m=MAX(tree[2*k+1].m,tree[2*k+2].m);
    tree[k].mIndex=tree[2*k+1].m>=tree[2*k+2].m ? tree[2*k+1].mIndex:tree[2*k+2].mIndex;
}

int getmax(int x,int y,int k,int& mindex) //从tree[k]查询[x y]的最大值,将下标保存到mindex
{
    if( x<=tree[k].a&&y>=tree[k].b )//x,y完全覆盖了tree[k]的区间
    {
        mindex=tree[k].mIndex;
        return tree[k].m;
    }

    int r=tree[k].r;
    tree[2*k+1].r+=r;tree[2*k+1].m+=r;
    tree[2*k+2].r+=r;tree[2*k+2].m+=r;
    tree[k].r=0;//将增量分发给了子区间

    int mid=(tree[k].a+tree[k].b)/2;
    int ret,mindex1,mindex2,r1,r2;
    if(x<=mid)//[x y]与左孩子有交集
    {
        if(y>=mid+1)//与右孩子也有交集
        {
            r1=getmax(x,y,2*k+1,mindex1);
            r2=getmax(x,y,2*k+2,mindex2);
            ret=MAX(r1,r2);
            mindex=r1>=r2? mindex1:mindex2;
        }
        else//只与左孩子有交集
        {
            ret=getmax(x,y,2*k+1,mindex1);
            mindex=mindex1;
        }
    }
    else//只与有孩子有交集
    {
        ret=getmax(x,y,2*k+2,mindex2);
        mindex=mindex2;
    }
    return ret;
}
int main()
{
    freopen("3.3.in","r",stdin);
    freopen("main.txt","w",stdout);
    int n,m;//糖果数,操作数
    int ans,mindex;
    string op;
    int x,y,p;
    while(cin>>n>>m,n)
    {
        build(1,n,0);//初始化线段树
        while(m--)
        {
            cin>>op;
            if(op=="I")
            {
                cin>>x>>y>>p;
                insert(x,y,p,0);
            }
            else
            {
                cin>>x>>y;
                ans=getmax(x,y,0,mindex);
                cout<<ans<<endl;
                insert(mindex,mindex,-ans,0);//取出糖果数
            }
        }
    }
    return 0;
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics