码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

2024-09-08 12:52

本文主要是介绍码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1🐋🐋配对最小值(王者;树状数组)

时间限制:1秒

占用内存:64M

🐟题目思路

MT3065 配对最小值_哔哩哔哩_bilibili

🐟代码

#include<bits/stdc++.h> 
using namespace std;
const int N=1e5+7;
int a[N],b[N],c[N],n,q;
struct QUERY{int l,r,id;
}query[N];
vector<pair<int,int> > items;
int lowbit(int x){return x&(-x);}
void update(int i,int x){for(;i<=n;i+=lowbit(i)) c[i]+=x;
}
int sum(int i){int ans=0;for(;i>0;i-=lowbit(i)) ans+=c[i];return ans;
}
bool cmp1(int x,int y){return a[x]<a[y];}
bool cmp2(pair<int,int> a,pair<int,int> b){return a.first>b.first;}
bool cmp3(QUERY a,QUERY b){return a.l>b.l;}
int main( )
{cin>>n>>q;for(int i=1;i<=n;i++){cin>>a[i];b[i]=i;}sort(b+1,b+1+n,cmp1);items.push_back({b[1],b[2]});items.push_back({b[n-1],b[n]});for(int i=2;i<n;i++){int val1=a[b[i]]-a[b[i-1]];int val2=a[b[i+1]]-a[b[i]];if(val1<=val2) items.push_back({b[i],b[i-1]});if(val2<=val1) items.push_back({b[i],b[i+1]});}for(auto &it:items)if(it.first>it.second)swap(it.first,it.second);sort(items.begin(),items.end(),cmp2);//降序for(int i=1;i<=q;i++) cin>>query[i].l>>query[i].r,query[i].id=i;sort(query+1,query+1+q,cmp3);int pos=0;long long ans=0;for(int i=1;i<=q;i++){while(pos<items.size()&&query[i].l<=items[pos].first)update(items[pos++].second,1);ans+=query[i].id*sum(query[i].r);}cout<<ans;return 0;
}

2🐋🐋三元组逆序对(星耀;树状数组)

时间限制:1秒

占用内存:64M

🐟题目思路

MT3067 三元组逆序对_哔哩哔哩_bilibili

🐟代码

#include<bits/stdc++.h> 
using namespace std;
#define int long long
const int N=5e5+7;
int n,a[N],tmp[N],c[N],ans,pre[N],suf[N];
int lowbit(int x){return x&(-x);}
void update(int i,int x){for(;i<=n;i+=lowbit(i)) c[i]+=x;
}
int sum(int i){int ans=0;for(;i>0;i-=lowbit(i)) ans+=c[i];return ans;
}
int sum(int l,int r){return sum(r)-sum(l-1);}signed main( )
{cin>>n;for(int i=1;i<=n;i++) cin>>a[i];//离散化for(int i=1;i<=n;i++) tmp[i]=a[i];sort(tmp+1,tmp+1+n);int len=unique(tmp+1,tmp+1+n)-(tmp+1);for(int i=1;i<=n;i++) a[i]=lower_bound(tmp+1,tmp+1+len,a[i])-tmp;//顺着看,前面多少数比自己大for(int i=1;i<=n;i++){update(a[i],1);pre[i]=sum(a[i]+1,n);}memset(c,0,sizeof(c));//逆着看,前面多少数比自己小for(int i=n;i>=1;i--){update(a[i],1);suf[i]=sum(a[i]-1);}for(int i=1;i<=n;i++) ans+=pre[i]*suf[i];cout<<ans;return 0;
}

3🐋🐋粉刷匠(星耀;线段树)

时间限制:1秒

占用内存:64M

🐟题目思路

MT3068 粉刷匠_哔哩哔哩_bilibili

🐟代码

#include<bits/stdc++.h> 
using namespace std;
const int N=5e4+10;
int a[N][15];
//num1初始化后的固定属性,相应区域1的个数;lz懒标记;ans是正确的个数,动态变化
struct NODE{int l,r,num1,lz,ans;
}tree[16][4*N];
void build(int tr,int p,int l,int r){tree[tr][p].lz=-1;tree[tr][p].l=l,tree[tr][p].r=r;if(l==r){tree[tr][p].num1=a[l][tr];tree[tr][p].ans=(a[l][tr]==0?1:0);return;}int mid=l+((r-l)>>1);build(tr,p*2,l,mid);build(tr,p*2+1,mid+1,r);tree[tr][p].num1=tree[tr][p*2].num1+tree[tr][p*2+1].num1;tree[tr][p].ans=tree[tr][p*2].ans+tree[tr][p*2+1].ans;
}
void lazy(int tr,int p,int v){int s=tree[tr][p].l,t=tree[tr][p].r;tree[tr][p].lz=v;if(v) tree[tr][p].ans=tree[tr][p].num1;else tree[tr][p].ans=t-s+1-tree[tr][p].num1;
}
void pushdown(int tr,int p){lazy(tr,2*p,tree[tr][p].lz);lazy(tr,2*p+1,tree[tr][p].lz);tree[tr][p].lz=-1;
}
void update(int tr,int p,int l,int r,int c){int s=tree[tr][p].l,t=tree[tr][p].r;if(l<=s&&t<=r) return lazy(tr,p,c);if(tree[tr][p].lz!=-1) pushdown(tr,p);int mid=s+((t-s)>>1);if(l<=mid) update(tr,p*2,l,r,c);if(r>mid) update(tr,p*2+1,l,r,c);tree[tr][p].ans=tree[tr][p*2].ans+tree[tr][p*2+1].ans;
}
int main( )
{int n,m,q;string str;cin>>n>>m>>q;for(int i=1;i<=n;i++){cin>>str;for(int j=1;j<=m;j++) a[i][j]=str[j-1]-'0';}for(int i=1;i<=m;i++) build(i,1,1,n);while(q--){int x1,x2,y1,y2,w,ans=0;cin>>x1>>x2>>y1>>y2>>w;for(int i=y1;i<=y2;i++) update(i,1,x1,x2,w);for(int i=1;i<=m;i++) ans+=tree[i][1].ans;cout<<ans<<endl;}return 0;
}

4🐋🐋偶数个数的异或和(星耀;树状数组)

时间限制:2秒

占用内存:125M

🐟题目思路

MT3066 偶数个数的异或和_哔哩哔哩_bilibili

🐟代码

#include<bits/stdc++.h> 
using namespace std;
const int N=1e6+7;
int n,a[N],c[N],sum[N],m,ans[N];
map<int,int> mp;
int lowbit(int x){return x&-x;}
void update(int i,int x){for(;i<=n;i+=lowbit(i)) c[i]^=x;
}
int query(int i){int ans=0;for(;i>0;i-=lowbit(i)) ans^=c[i];return ans;
}
struct QUERY{int l,r,id;bool operator<(const QUERY &x) const{return r<x.r;}
}q[N];
int main( )
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i];sum[i]=sum[i-1]^a[i];}cin>>m;for(int i=1;i<=m;i++){cin>>q[i].l>>q[i].r;q[i].id=i;}sort(q+1,q+1+m);int pos=1;for(int i=1;i<=m;i++){while(pos<=q[i].r){if(mp.find(a[pos])!=mp.end()){update(mp[a[pos]],a[pos]);update(pos,a[pos]);mp[a[pos]]=pos;}else{mp[a[pos]]=pos;update(pos,a[pos]);}pos++;}ans[q[i].id]=sum[q[i].l-1]^sum[q[i].r]^query(q[i].r)^query(q[i].l-1);}for(int i=1;i<=m;i++) cout<<ans[i]<<endl;return 0;
}

5🐋🐋宝石的魔力波动(星耀;线段树)

时间限制:3秒

占用内存:512M

🐟题目思路

MT3069 宝石的魔力波动_哔哩哔哩_bilibili

🐟代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct NODE
{int l, r, cnt, lz;vector<int> val;
} tree[4 * N];
int n, m, a[N];
vector<int> ans;
void lazy(int p, int v)
{tree[p].lz += v;for (int i = 0; i < tree[p].cnt; i++){tree[p].val[i] += v;}
}
void pushdown(int p)
{lazy(p * 2, tree[p].lz);lazy(p * 2 + 1, tree[p].lz);tree[p].lz = 0;
}
void pushup(int p)
{vector<int> tmp;int i = 0, j = 0;int cnt_l = tree[p * 2].cnt, cnt_r = tree[p * 2 + 1].cnt;vector<int> val_l = tree[p * 2].val, val_r = tree[p * 2 + 1].val;while (i < cnt_l && j < cnt_r){tmp.emplace_back(val_l[i] > val_r[j] ? val_l[i++] : val_r[j++]);}while (i < cnt_l)tmp.emplace_back(val_l[i++]);while (j < cnt_r)tmp.emplace_back(val_r[j++]);tree[p].val.clear();for (int i = 0; i < tree[p].cnt; i++){tree[p].val.emplace_back(tmp[i]);}
}
void build(int p, int l, int r)
{tree[p].l = l, tree[p].r = r;if (l == r){tree[p].cnt = 1;tree[p].val.emplace_back(a[l]);return;}int mid = l + ((r - l) >> 1);build(p * 2, l, mid);build(p * 2 + 1, mid + 1, r);tree[p].cnt = min(tree[p * 2].cnt + tree[p * 2 + 1].cnt, 36);pushup(p);
}
void update(int l, int r, int c, int p)
{int s = tree[p].l, t = tree[p].r;if (l <= s && t <= r){return lazy(p, c);}if (tree[p].lz)pushdown(p);int mid = s + ((t - s) >> 1);if (l <= mid)update(l, r, c, p * 2);if (r > mid)update(l, r, c, p * 2 + 1);pushup(p);
}
void merge(int p)
{vector<int> tmp;int i = 0, j = 0, cnt = tree[p].cnt;vector<int> val = tree[p].val;while (i < cnt && j < ans.size()){tmp.emplace_back(val[i] > ans[j] ? val[i++] : ans[j++]);}while (i < cnt)tmp.emplace_back(val[i++]);while (j < ans.size())tmp.emplace_back(ans[j++]);ans.clear();for (int i = 0; i < min((int)tmp.size(), 36); i++)ans.emplace_back(tmp[i]);
}
void query(int l, int r, int p)
{int s = tree[p].l, t = tree[p].r;if (l <= s && t <= r){merge(p);return;}if (tree[p].lz)pushdown(p);int mid = s + ((t - s) >> 1);if (l <= mid)query(l, r, p * 2);if (r > mid)query(l, r, p * 2 + 1);return;
}
int op, l, r, v;
int main()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> a[i];build(1, 1, n);while (m--){cin >> op >> l >> r;if (op == 1){cin >> v;update(l, r, v, 1);}else{if (l == r){cout << "-1" << endl;continue;}ans.clear();query(l, r, 1);int res = 0;for (int i = 0; i < ans.size(); i++)for (int j = i + 1; j < ans.size(); j++)res = max(res, ans[i] & ans[j]);cout << res << endl;}}return 0;
}

创作不易,点个赞吧~

点赞收藏不迷路~

这篇关于码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1148162

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

HDU4737线段树

题目大意:给定一系列数,F(i,j)表示对从ai到aj连续求或运算,(i<=j)求F(i,j)<=m的总数。 const int Max_N = 100008 ;int sum[Max_N<<2] , x[Max_N] ;int n , m ;void push_up(int t){sum[t] = sum[t<<1] | sum[t<<1|1] ;}void upd

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;