一、 线段树
P2412 查单词 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://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)https://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)https://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)https://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)https://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;
}