铺设道路(2018noip提高组)(贪心,线段树,树状数组)

文章介绍了AcWing在线编程题531的解决方案,包括使用贪心算法和线段树数据结构来处理道路铺设问题。贪心算法中,通过计算相邻道路长度差并累加正差值求解。线段树方法中,构建线段树并进行区间更新与查询,找到非零差值区间并更新答案。

531. 铺设道路 - AcWing题库

铺设道路 - 蓝桥云课 (lanqiao.cn)

目录

贪心写法

线段树写法

数组数组写法


 输入

6   
4 3 2 5 3 5 

输出

9

贪心写法

#include <iostream>
#include <bits/stdc++.h>
#include <cstring>
#include <vector>
#include <unordered_map>
#include <queue>
#include <set>
#define int long long 
#include <algorithm>
#define x first
#define y second
#define pb emplace_back
#define fu(i,a,b) for(int i=a;i<=b; ++ i)
#define fd(i,a,b) for(int i=a;i>=b; -- i)
#define endl '\n'
#define ms(x,y) memset(x,y,sizeof x)
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<vector<LL>> VVL;
typedef vector<vector<int>> VVI;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef pair<PII,int> PIII;
typedef pair<double,double> PDD;
typedef pair<double,int> PDI;
typedef pair<char,int> PCI;
typedef pair<string,int> PSI;
typedef pair<int,string> PIS;
typedef pair<int,char> PIC;
typedef pair<LL,LL> PLL;
typedef __int128 i128;
typedef unsigned long long ULL;
const int N =1e5 + 10,M = N * 5,base =400  ,INF = 0x3f3f3f3f,P = 131;
const double eps = 1e-8;
const int mod = 998244353;
const LL LNF=(LL) INF * INF;

int f[N];
int a[N];
int n,ans;





inline void solve()
{
    cin >> n ;
    fu(i,1,n) cin >> a[ i];
    fu(i,1,n) f[i]= a[i] - a[i-1];

    fu(i,1,n)
    if(f[i] >  0 ) ans += f[i];
    cout << ans << endl;    

}
signed main()
{
//  freopen("1.txt","r",stdin);
//  #define int long long 
//  init(N-1);
    ios
//  cout << fixed<<setprecision(2);
    int t=1;
//    cin>>t;
    int now = 1;
    while(t -- )
    {
//      cout<<"Case "; 
//      cout<<"Case #"; 
//      cout<<"Scenario #"; 
//      cout<< now ++ <<": ";
//      cout<< now ++ <<": \n";
        solve();
    }


    return 0;
}


线段树写法

#include <iostream>
#include <bits/stdc++.h>
#include <cstring>
#include <vector>
#include <unordered_map>
#include <queue>
#include <set>
#define int long long 
#include <algorithm>
#define x first
#define y second
#define pb emplace_back
#define fu(i,a,b) for(int i=a;i<=b; ++ i)
#define fd(i,a,b) for(int i=a;i>=b; -- i)
#define endl '\n'
#define ms(x,y) memset(x,y,sizeof x)
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<vector<LL>> VVL;
typedef vector<vector<int>> VVI;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef pair<PII,int> PIII;
typedef pair<double,double> PDD;
typedef pair<double,int> PDI;
typedef pair<char,int> PCI;
typedef pair<string,int> PSI;
typedef pair<int,string> PIS;
typedef pair<int,char> PIC;
typedef pair<LL,LL> PLL;
typedef __int128 i128;
typedef unsigned long long ULL;
const int N =1e5 + 10,M = N * 5,base =400  ,INF = 0x3f3f3f3f,P = 131;
const double eps = 1e-8;
const int mod = 998244353;
const LL LNF=(LL) INF * INF;

int n,a[N],m;

struct node{
    int l,r,minn,minp,lazy;
    bool operator<(const node &W )const
    {
        return minn < W.minn;
    }

}tr[N * 4 ];

void pushup(int u)
{
    if(tr[u<<1].minn < tr[u << 1 | 1 ].minn)
    {
        tr[u].minn = tr[u<<1].minn;
        tr[u].minp = tr[u<<1].minp;
    }
    else 
    {
        tr[u].minn = tr[u<<1|1].minn;
        tr[u].minp = tr[u<<1|1].minp;
    }

}

void pushdown(int u)
{
    auto &t = tr[u].lazy;
    auto &l = tr[u << 1],&r = tr[u<<1|1];

    l.minn -=t;r.minn -= t;
    l.lazy += t;r.lazy += t;
    t =0 ;
}

void build(int u,int l,int r)
{
    if(l == r) 
    {
        tr[u] = {l,r,a[l],l};return;
    }
    tr[u]={l,r};
    int mid = l + r >> 1 ;
    build(u << 1 ,l ,mid );
    build(u << 1 | 1 ,mid + 1 , r  );
    pushup(u);
}


void modify(int u,int l,int r,int v)
{
    if(tr[u].l >= l && tr[u].r <= r )
    {
        tr[u].minn -= v;tr[u].lazy += v;return;
    }

    pushdown(u);

    int mid = tr[u].l + tr[u].r >> 1; 

    if(l <= mid ) modify(u<<1,l,r,v);
    if(r > mid ) modify(u<<1|1,l,r,v);
    pushup(u);

}

node query(int u,int l,int r)
{
    if(tr[u].l >= l && tr[u].r <= r ) return tr[u];

    int mid = tr[u].l + tr[u].r >> 1;
    node res ;res.minn = INF ;
    pushdown(u);

    if(l <= mid ) res = min(res,query(u<<1,l,r));
    if( r > mid ) res = min(res,query(u<<1|1,l,r));
    return res;
}

int get_ans(int l,int r)
{
    int res=0;
    node now = query(1,l,r);

    if(now.minn)
    {
        modify(1,l,r,now.minn);res += now.minn;
    }
    if(now.minp > l ) res += get_ans(l,now.minp -1);
    if(now.minp < r ) res += get_ans(now.minp + 1 ,r );
    return res;
}



inline void solve()
{
    cin >> n ;
    fu(i,1,n) cin >> a[i];

    build(1,1,n);

    cout << get_ans(1,n) << endl;


}
signed main()
{
//  freopen("1.txt","r",stdin);
//  #define int long long 
//  init(N-1);
    ios
//  cout << fixed<<setprecision(2);
    int t=1;
//    cin>>t;
    int now = 1;
    while(t -- )
    {
//      cout<<"Case "; 
//      cout<<"Case #"; 
//      cout<<"Scenario #"; 
//      cout<< now ++ <<": ";
//      cout<< now ++ <<": \n";
        solve();
    }


    return 0;
}

数组数组写法

#include <iostream>
#include <bits/stdc++.h>
#include <cstring>
#include <vector>
#include <unordered_map>
#include <queue>
#include <set>
#define int long long 
#include <algorithm>
#define x first
#define y second
#define pb emplace_back
#define fu(i,a,b) for(int i=a;i<=b; ++ i)
#define fd(i,a,b) for(int i=a;i>=b; -- i)
#define endl '\n'
#define ms(x,y) memset(x,y,sizeof x)
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<vector<LL>> VVL;
typedef vector<vector<int>> VVI;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef pair<PII,int> PIII;
typedef pair<double,double> PDD;
typedef pair<double,int> PDI;
typedef pair<char,int> PCI;
typedef pair<string,int> PSI;
typedef pair<int,string> PIS;
typedef pair<int,char> PIC;
typedef pair<LL,LL> PLL;
typedef __int128 i128;
typedef unsigned long long ULL;
const int N =1e5 + 10,M = N * 5,base =400  ,INF = 0x3f3f3f3f,P = 131;
const double eps = 1e-8;
const int mod = 998244353;
const LL LNF=(LL) INF * INF;

int n,a[N],tr[N];

int lowbit(int x)
{
    return x & -x;
}

void add(int x,int v)
{
    for(int i=x;i<=n; i+= lowbit(i)) tr[i] += v;
}

int query(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i)) res += tr[i];
    return res;
}
PII search(int mid)
{
    int l= mid,r =mid;

    while(query(l) && l >=1 ) l -- ;
    l ++ ;
    while(query(r) && r <= n ) r ++ ;
    r -- ;

    if(!l) l = 1;
    if(r == n + 1 ) r = n ;
    return {l,r};

}

inline void solve()
{
    cin >> n;
    priority_queue<PII,vector<PII>,greater<PII>> q; 
    fu(i,1,n) 
    {
        cin >> a[i];
        q.push({a[i],i});
        add(i,a[i]);
        add(i+1,-a[i]);
// 树状数组 加值的时候 有点像 差分        
    }

    int res=0;

    while(q.size() )
    {
        auto t= q.top() ;q.pop() ;
        int pos = t.y,w = query(pos);
// 当前最小值 的位置, 最小值的值     
        if(w)
        {
            PII seg = search(pos);
// 最小值 所在的 一段 非0区间          
            add(seg.x,-w); // [l,r] -=w
            add(seg.y+1,w);
        }
        res += w;
    }
    cout << res << endl;


}
signed main()
{
//  freopen("1.txt","r",stdin);
//  #define int long long 
//  init(N-1);
    ios
//  cout << fixed<<setprecision(2);
    int t=1;
//    cin>>t;
    int now = 1;
    while(t -- )
    {
//      cout<<"Case "; 
//      cout<<"Case #"; 
//      cout<<"Scenario #"; 
//      cout<< now ++ <<": ";
//      cout<< now ++ <<": \n";
        solve();
    }


    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值