洛谷——查单词+简单题+火车线路 +无聊的数列+最大数——线段树

一、 线段树

P2412 查单词 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P2412


解析:
板子题,区间搜索,不需要区间修改

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
// int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
// typedef unsigned long long ULL;
// typedef pair<int, int> PII;
// const double PI = acos(-1.0);
const int N=1e5+10;
struct node
{
    string s,p;
}tr[4*N];
string k[N],kk[N];
void push_up (int u)
{
    string a=tr[u<<1].s,b=tr[u<<1|1].s;
    if (a>b) tr[u]=tr[u<<1];
    else tr[u]=tr[u<<1|1];
}
node push_up(node l,node r)
{
    string a=l.s,b=r.s;
    if (a>b) return l;
    return r;
}
void build (int u,int l,int r)
{
    if (l==r)
    {
        tr[u].p=k[l],tr[u].s=kk[l];
        return ;
    }
    int mid=l+r>>1;
    build (u<<1,l,mid), build (u<<1|1,mid+1,r);
    push_up(u);
}
node query(int L,int R,int u,int l,int r)
{
    if (l>=L&&r<=R) return tr[u];
    int mid=l+r>>1;
    node res;
    if (L<=mid&&mid<R) res=push_up(query(L,R,u<<1,l,mid),query(L,R,u<<1|1,mid+1,r));
    else if (L<=mid) res=query(L,R,u<<1,l,mid);
    else if (mid<R) res=query(L,R,u<<1|1,mid+1,r);
    return res;
}
int n,m;
void solve()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++)
    {
        cin>>k[i];
        string s;
        for (int j=0;j<k[i].size();j++)
        {
            if (k[i][j]>='A'&&k[i][j]<='Z') s +=k[i][j]+32;
            else s +=k[i][j];
        }
        kk[i]=s;
    }
    build (1,1,n);
    for (int i=1;i<=m;i++)
    {
        int l,r;
        cin>>l>>r;
        cout<<query(l,r,1,1,n).p<<endl;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //cin >> T;
    while (T--) solve();
    return 0;
}

二、树状数组(也可用线段树)

P5057 [CQOI2006] 简单题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P5057解析:
只需要单点查询和区间修改,是否存在用 &1判断

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
// int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
// typedef unsigned long long ULL;
// typedef pair<int, int> PII;
// const double PI = acos(-1.0);
const int N=1e6+10;
int tr[N];
int n,m;
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int c)
{
    for (int i=x;i<=n;i +=lowbit(i)) tr[i] +=c;
}
int query(int x)
{
    int ans=0;
    for (int i=x;i>0;i -=lowbit(i)) ans +=tr[i];
    return ans;
}
void solve()
{
    cin>>n>>m;
    int op,l,r,x;
    for (int i=1;i<=m;i++)
    {
        cin>>op;
        if (op==1)
        {
            cin>>l>>r;
            add(l,1),add(r+1,-1);
        }
        else 
        {
            cin>>x;
            cout<<(query(x)&1)<<endl;
        }
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //cin >> T;
    while (T--) solve();
    return 0;
}

三、线段树

P8856 [POI2002] 火车线路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P8856解析:
显然,我们可以把这道题转换成数列区间最小值的问题,然后用线段树。
我们每处理一个预定,如果可以满足,即这一段区间里所有的数都大于等于预定的数,那么我们就把区间里的所有数都减去这个数。否则的话就是不能满足。
需要push_down操作。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
// int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
// typedef unsigned long long ULL;
// typedef pair<int, int> PII;
// const double PI = acos(-1.0);
const int N=1e6+10;
struct node
{
    int mi;
}tr[4*N];
int mark[N];
void push_up (int u)
{
    tr[u].mi=min(tr[u<<1].mi,tr[u<<1|1].mi);
}
void push_down (int u,int l,int r)
{
    int mid=l+r>>1;
    tr[u<<1].mi +=mark[u];
    tr[u<<1|1].mi +=mark[u];
    mark[u<<1] +=mark[u];
    mark[u<<1|1] +=mark[u];
    mark[u]=0;
}
void build (int u,int l,int r,int R)
{
    if (l==r)
    {
        tr[u].mi=R;
        return ;
    }
    int mid=l+r>>1;
    build (u<<1,l,mid,R),build (u<<1|1,mid+1,r,R);
    push_up(u);
}
int query (int L,int R,int u,int l,int r)
{
    if (l>=L&&r<=R) return tr[u].mi;
    push_down(u,l,r);
    int mid=l+r>>1;
    int res=0;
    if (L<=mid&&mid<R) res=min(query(L,R,u<<1,l,mid),query(L,R,u<<1|1,mid+1,r));
    else if (L<=mid) res=query(L,R,u<<1,l,mid);
    else if (mid<R) res=query(L,R,u<<1|1,mid+1,r);
    return res;
}
void modify (int L,int R,int d,int u,int l,int r)
{
    if (l>=L&&r<=R) 
    {
        tr[u].mi +=d;
        mark[u] +=d;
        return ;
    }
    push_down(u,l,r);
    int mid=l+r>>1;
    if (L<=mid) modify(L,R,d,u<<1,l,mid);
    if (mid<R) modify(L,R,d,u<<1|1,mid+1,r);
    push_up(u);
}
void solve()
{
    int n,R,c;
    cin>>n>>R>>c;
    build (1,1,n,R);
    while (c--)
    {
        int o,d,m;
        cin>>o>>d>>m;
        int k=query(o,d-1,1,1,n);
        if (k>=m)
        {
            cout<<"T\n";
            modify(o,d-1,-m,1,1,n);
        }
        else cout<<"N\n";
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //cin >> T;
    while (T--) solve();
    return 0;
}

四、线段树+差分

P1438 无聊的数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1438解析:
令等差序列的首项为 s,末项为 e,公差为 d。
如果要在差分序列上加一个等差序列,就要在a[l]加上s,a[l+1]~a[r]加上d,a[r+1]减去e。
线段树维护的是差分序列,单点查询 x 就是 1~x 的前缀和。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
// int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
// typedef unsigned long long ULL;
// typedef pair<int, int> PII;
// const double PI = acos(-1.0);
const int N=2e5+10;
struct node 
{
    int sum;
}tr[4*N];
int mark[4*N];
int n,m;
int a[N],b[N];
void push_up(int u)
{
    tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void push_down(int u,int l,int r)
{
    int mid=l+r>>1;
    tr[u<<1].sum +=mark[u]*(mid-l+1);
    tr[u<<1|1].sum +=mark[u]*(r-mid);
    mark[u<<1] +=mark[u];
    mark[u<<1|1] +=mark[u];
    mark[u]=0;
}
void build (int u,int l,int r)
{
    if (l==r)
    {
        tr[u].sum=b[l];
        return ;
    }
    int mid=l+r>>1;
    build(u<<1,l,mid), build(u<<1|1,mid+1,r);
    push_up(u);
}
void modify(int L,int R,int d,int u,int l,int r)
{
    if (l>=L&&r<=R) 
    {
        tr[u].sum +=(r-l+1)*d;
        mark[u] +=d;
        return ;
    }
    push_down(u,l,r);
    int mid=l+r>>1;
    if (L<=mid) modify(L,R,d,u<<1,l,mid);
    if (mid<R) modify(L,R,d,u<<1|1,mid+1,r);
    push_up(u);
}
int query(int L,int R,int u,int l,int r)
{
    if (l>=L&&r<=R) return tr[u].sum;
    push_down(u,l,r);
    int mid=l+r>>1;
    int res=0;
    if (L<=mid&&mid<R)
    {
        res=query(L,R,u<<1,l,mid)+query(L,R,u<<1|1,mid+1,r);
    }
    else if (L<=mid) res=query(L,R,u<<1,l,mid);
    else if (mid<R) res=query(L,R,u<<1|1,mid+1,r);
    return res;
}
void solve()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>a[i];
    for (int i=1;i<=n;i++) b[i]=a[i]-a[i-1];
    build (1,1,n);
    for (int i=1;i<=m;i++)
    {
        int op,l,r,k,d,x;
        cin>>op;
        if (op==1)
        {
            cin>>l>>r>>k>>d;
            modify(l,l,k,1,1,n);
            if (l<r) modify(l+1,r,d,1,1,n);
            if (r<n) modify(r+1,r+1,-(k+(r-l)*d),1,1,n);
        }
        else 
        {
            cin>>x;
            cout<<query(1,x,1,1,n)<<endl;
        }
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) solve();
    return 0;
}

五、线段树

P1198 [JSOI2008] 最大数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1198解析:

板子题,看代码,也不需要push_down操作。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
// int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
// typedef unsigned long long ULL;
// typedef pair<int, int> PII;
// const double PI = acos(-1.0);
const int N=2e5+10;
struct node
{
    int ma;
}tr[4*N];
void push_up(int u)
{
    tr[u].ma=max(tr[u<<1].ma,tr[u<<1|1].ma);
}
void modify(int x,int d,int u,int l,int r)
{
    if (l==x&&x==r)
    {
        tr[u].ma=d;
        return ;
    }
    int mid=l+r>>1;
    if (x<=mid) modify(x,d,u<<1,l,mid);
    else modify(x,d,u<<1|1,mid+1,r);
    push_up(u);
}
int query(int L,int R,int u,int l,int r)
{
    if (l>=L&&r<=R) return tr[u].ma;
    int mid=l+r>>1;
    int res=-1e18;
    if (L<=mid&&mid<R) res=max(query(L,R,u<<1,l,mid),query(L,R,u<<1|1,mid+1,r));
    else if (L<=mid) res=query(L,R,u<<1,l,mid);
    else if (mid<R) res=query(L,R,u<<1|1,mid+1,r);
    return res;
}
int m,d;
void solve()
{
    cin>>m>>d;
    string s;
    int x;
    int n=0;
    int t=0;
    for (int i=1;i<=m;i++)
    {
        cin>>s>>x;
        if (s=="A") 
        {
            modify(n+1,(x+t)%d,1,1,m),n++;
        }
        else 
        {
            cout<<query(n-x+1,n,1,1,m)<<endl;
            t=query(n-x+1,n,1,1,m);
        }
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //cin >> T;
    while (T--) solve();
    return 0;
}

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值