线段树模板

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 1000
#define inf 1000000
using namespace std;

class segtree
{
public:
    int val,addmark;
};

segtree segt[maxn<<2];
int a[maxn];

void build(int root,int beg,int en)
{
    if (beg==en)
        {segt[root].val=a[beg];segt[root].addmark=0;return;}
    else
    {
        int mid=(beg+en)/2;
        build(root*2,beg,mid);
        build(root*2+1,mid+1,en);
    }
    segt[root].val=min(segt[root*2].val,segt[root*2+1].val);//改这里
    segt[root].addmark=0;
}

void pushdown(int root)
{
    if (segt[root].addmark!=0)
    {
        segt[root*2].val+=segt[root].addmark;
        segt[root*2].addmark+=segt[root].addmark;
        segt[root*2+1].val+=segt[root].addmark;
        segt[root*2+1].addmark+=segt[root].addmark;
        segt[root].addmark=0;
    }
    return;
}

void update(int root,int rst,int ren,int beg,int en,int val)//update是加上一个数,如果是变成一个数,那就需要改update
{
    if (rst>=beg&&ren<=en)
    {
        segt[root].val+=val;
        segt[root].addmark+=val;
    }
    else if (rst>en||ren<beg) {return;}
    else
    {
        pushdown(root);
        int mid=(rst+ren)/2;
        update(root*2,rst,mid,beg,en,val);
        update(root*2+1,mid+1,ren,beg,en,val);
        segt[root].val=min(segt[root*2].val,segt[root*2+1].val);//改这里
    }
}

int query(int root,int rst,int ren,int beg,int en)
{
    if (rst>en||ren<beg)
        return inf;//改这里
    if (rst==beg&&ren==en)
        return segt[root].val;
    pushdown(root);
    int mid=(rst+ren)/2;

    if (en<=mid)
        return query(root*2,rst,mid,beg,en);
    else if (beg>=mid+1)
        return query(root*2+1,mid+1,ren,beg,en);
    else
        return min(query(root*2,rst,mid,beg,mid),query(root*2+1,mid+1,ren,mid+1,en));//改这里
}

int main()
{
    memset(segt,0,sizeof(segt));
    for(int k=1;k<=10;k++)
        scanf("%d",&a[k]);
    build(1,1,10);
    int i,j,val;
   // cin>>i>>j>>val;
   // update(1,1,10,i,j,val);

    while(scanf("%d %d",&i,&j))
    {
        cout<<query(1,1,10,i,j)<<endl;
    }


    return 0;

}

最近做了到题目,就是给m个区间
对于第i个区间li,ri至少要取ki个点,要求至少要取多少个点
这个题目就是贪心,将所有区间按右端点从小到大排序
然后对于每个区间从右往左取,直到满足要求
很好的题目,现在放上ac代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 505000
#define inf 1000000
using namespace std;

class segtree
{
public:
    int val,addmark;
};

segtree segt[maxn<<2];

void pushdown(int root)
{
    if (segt[root].addmark!=0)
    {
        segt[root*2].val+=segt[root].addmark;
        segt[root*2].addmark+=segt[root].addmark;
        segt[root*2+1].val+=segt[root].addmark;
        segt[root*2+1].addmark+=segt[root].addmark;
        segt[root].addmark=0;
    }
    return;
}

void update(int root,int rst,int ren,int beg,int en,int val)
{
    if (rst>=beg&&ren<=en)
    {
        segt[root].val+=val;
        segt[root].addmark+=val;
    }
    else if (rst>en||ren<beg) {return;}
    else
    {
        pushdown(root);
        int mid=(rst+ren)/2;
        update(root*2,rst,mid,beg,en,val);
        update(root*2+1,mid+1,ren,beg,en,val);
        segt[root].val=segt[root*2].val+segt[root*2+1].val;
    }
}

int query(int root,int rst,int ren,int beg,int en)
{
    if (rst>en||ren<beg)
        return 0;
    if (rst==beg&&ren==en)
        return segt[root].val;
    pushdown(root);
    int mid=(rst+ren)/2;

    if (en<=mid)
        return query(root*2,rst,mid,beg,en);
    else if (beg>=mid+1)
        return query(root*2+1,mid+1,ren,beg,en);
    else
        return query(root*2,rst,mid,beg,mid)+query(root*2+1,mid+1,ren,mid+1,en);
}

struct Data
{
    int l,r,k;
};

Data a[1001000];

bool cmp(Data aa,Data bb)
{
    return aa.r<bb.r;
}

int vis[maxn];

int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for (int k=1;k<=m;k++)
            scanf("%d %d %d",&a[k].l,&a[k].r,&a[k].k);

        sort(a+1,a+1+m,cmp);

        memset(segt,0,sizeof(segt));
        memset(vis,0,sizeof(vis));

        for (int k=1;k<=m;k++)
        {
            int save=query(1,1,n,a[k].l,a[k].r);
            int poi=a[k].r;

            while(save<a[k].k)
            {
                while(vis[poi])
                    poi--;
                update(1,1,n,poi,poi,1);
                vis[poi]=1;
                save++;
            }
        }

        printf("%d\n",query(1,1,n,1,n));
    }
    return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值