算法进阶指南
算法进阶指南,经典中的经典
辉小歌
九局下半转啊转,我把帽子反戴,还在期待逆转。
展开
-
173. 矩阵距离【多源 BFS】
#include<bits/stdc++.h>using namespace std;const int N=1010;int a[N][N],dist[N][N],st[N][N],n,m;void solve(){ int dx[4]={-1,0,0,1}; int dy[4]={0,-1,1,0}; queue<pair<int,int>>q; for(int i=1;i<=n;i++) for(in.原创 2022-03-25 02:00:42 · 644 阅读 · 0 评论 -
188. 武士风度的牛【bfs】
#include<bits/stdc++.h>using namespace std;const int N=210;char a[N][N];int st[N][N],n,m;int startx,starty,endx,endy;struct node{int x,y,step;};int dx[10]={-2,-2,-1,1,-1,1,2,2};int dy[10]={-1,1,-2,-2,2,2,-1,1};int bfs(){ queue<node&.原创 2022-03-25 01:50:51 · 504 阅读 · 0 评论 -
136. 邻值查找【set lower_bound】
set的lower_bound没找到返回的迭代器就是 st.end()#include<bits/stdc++.h>using namespace std;const int N=1e5+10;int a[N],n;map<int,int>mp;int main(void){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]=i; set<int>st; .原创 2022-03-25 01:17:51 · 757 阅读 · 0 评论 -
125. 耍杂技的牛【贪心】
#include<bits/stdc++.h>using namespace std;#define x first#define y secondtypedef pair<int,int> PII;typedef long long int LL;LL n,ans=-1e9,s;vector<PII>ve;bool cmp(PII a,PII b){return a.x+a.y<b.x+b.y;}int main(void){ cin.原创 2022-03-24 01:29:26 · 457 阅读 · 0 评论 -
122. 糖果传递【均分纸牌问题】
#include<bits/stdc++.h>using namespace std;const int N=1e6+10;typedef long long int LL;LL a[N],s[N],c[N],n;int main(void){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i],s[i]=s[i-1]+a[i]; LL avg=s[n]/n; for(int i=1;i<.原创 2022-03-24 01:20:42 · 248 阅读 · 0 评论 -
114. 国王游戏【高精度+贪心】
#include<bits/stdc++.h>using namespace std;typedef pair<int,int> PII;const int N=1e5+10;bool cmp(PII a,PII b){ return a.first*a.second<b.first*b.second;}vector<PII>ve;vector<int> mul(vector<int>& A,int b)..原创 2022-03-21 01:06:46 · 5709 阅读 · 2 评论 -
112. 雷达设备【贪心】
呢么问题就变成了区间合并问题。给我们n给区间将相交的区间合并求不相交的区间个数。#include<bits/stdc++.h>using namespace std;typedef pair<double,double> pdd;int n,r,flag;vector<pdd>ve; int main(void){ cin>>n>>r; for(int i=0;i<n;i++) { d..原创 2022-03-21 00:33:24 · 189 阅读 · 0 评论 -
111. 畜栏预定【贪心】
经典的贪心问题,和分组问题很像。不过这里我们还得维护坐标信息。#include<bits/stdc++.h>using namespace std;#define x first#define y second;const int N=1e5+10;typedef pair<int,int> PII;struct node{int l,r,id;};bool cmp(node a,node b){ if(a.l!=a.l) return a.r<b..原创 2022-03-20 01:28:46 · 164 阅读 · 0 评论 -
105. 七夕祭【环形均分纸牌问题】
首先你会发现,行交换和列交换是无影响的。故可以分开讨论。这不就变成了环形均分纸牌的问题了么,和蓝桥杯糖果那题类似。#include<bits/stdc++.h>using namespace std;const int N=1e5+10;typedef long long int LL;LL x[N],y[N],c[N],n,m,t;LL solve(LL s[],int n){ LL avg=s[n]/n; for(int i=1;i<=n;i++) .原创 2022-03-20 01:06:15 · 263 阅读 · 0 评论 -
97. 约数之和【数学 快速幂】
#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int mod=9901;LL a,b;LL quick_mi(LL a,LL b){ LL sum=1; while(b) { if(b&1) sum=sum*a%mod; b>>=1; a=a*a%mod; } return..原创 2022-03-20 00:06:04 · 164 阅读 · 0 评论 -
131. 直方图中最大的矩形【单调栈】
单调栈的经典应用。找到左边最近的比它小的,找到右边的最近的比它小的。#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int N=1e5+10;LL h[N],lmin[N],rmin[N],n;int main(void){ while(cin>>n,n) { for(int i=1;i<=n;i++) scanf("%lld",&.原创 2022-03-19 00:13:58 · 290 阅读 · 0 评论 -
152. 城市游戏【单调栈】
131. 直方图中最大的矩形 这一道题的变种。我们只多了枚举所有的地面#include<bits/stdc++.h>using namespace std;const int N=1010;int s[N][N],a[N],n,m;char c[N][N];int solve(int x){ for(int i=1;i<=m;i++) a[i]=s[x][i]; int lmin[N]={0},rmin[N]={0}; a[0]=-1,a[m+1]=.原创 2022-03-19 00:07:54 · 3411 阅读 · 0 评论 -
242. 一个简单的整数问题【树状数组 区间加 单点和】
用差分来实现区间加。#include<bits/stdc++.h>using namespace std;const int N=1e5+10;int tr[N],a[N],n,m;int lowbit(int x){return x&(-x);}void add(int u,int x){ for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x;}int query(int u){ int sum=0; for.原创 2022-03-18 01:00:23 · 264 阅读 · 0 评论 -
165. 小猫爬山【爆搜+剪枝】
#include<bits/stdc++.h>using namespace std;const int N=25;int w[N],s[N],n,m,ans,len=0;void dfs(int index){ if(len>=ans) return; if(index==n) { ans=min(ans,len); return; } for(int i=0;i<len;i++)//枚举猫放在现有.原创 2022-03-18 00:52:59 · 834 阅读 · 0 评论 -
197. 阶乘分解【数论】
n!中2出现的次数==n!/2+n!/4+n!/8............#include<bits/stdc++.h>using namespace std;const int N=1e6+10;int prime[N],st[N],cnt,n;void init(int n){ for(int i=2;i<=n;i++) { if(!st[i]) prime[cnt++]=i; for(int j=0;prime[j]<.原创 2022-03-18 00:38:13 · 347 阅读 · 0 评论 -
148. 合并果子【哈夫曼树】
#include<bits/stdc++.h>using namespace std;typedef long long int LL;int n,x;priority_queue<LL,vector<LL>,greater<LL>>q;int main(void){ cin>>n; for(int i=0;i<n;i++) cin>>x,q.push(x); LL ans=0; wh.原创 2022-03-17 17:37:16 · 423 阅读 · 0 评论 -
164. 可达性统计【拓扑排序 / bitset】
无环说明一定有拓扑排序。我们得到拓扑排序,倒着推。注意压位。#include<bits/stdc++.h>#include<bitset>using namespace std;const int N=30010;int h[N],e[N],ne[N],idx;int d[N],n,m;vector<int>ve;bitset<N>cnt[N]; //每一个点压了N位。1表示可以到达,0表示不可以到达void add(int a,int.原创 2022-03-17 11:17:26 · 254 阅读 · 0 评论 -
135. 最大子序和【前缀和 单调队列】
将其转化成前缀和数组,问题就转化成了,对于固定的右端点,找到前面一个窗口大小不大于m的最小的左端点。就是单调队列#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int N=1e5*5+10;LL a[N],s[N],n,m;int main(void){ cin>>n>>m; for(int i=1;i<=n;i++) cin>.原创 2022-03-17 10:33:33 · 236 阅读 · 0 评论 -
41. 包含min函数的栈【单调栈】
用一个单调栈,来维护。单调栈的栈头就是最小值。class MinStack {public: /** initialize your data structure here. */ stack<int>minv; stack<int>st; MinStack() { } void push(int x) { st.push(x); if(minv.empty().原创 2022-03-17 00:26:00 · 206 阅读 · 0 评论 -
108. 奇数码问题【思维 / 逆序对】
n为奇数,左右交换不改变逆序对数个数,上下交换不改变逆序对奇偶性。结论就是,将其转化成1维,将0去除掉,求逆序对的数量,看这两个的逆序对的奇偶性是否相同即可。#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int N=1e5*3+10;int n,temp[N];void merge_sort(int l,int r,vector<int>&a,LL &.原创 2022-03-17 00:05:58 · 268 阅读 · 0 评论 -
129. 火车进栈【栈】
#include<bits/stdc++.h>using namespace std;vector<int>ve;stack<int>st;int cnt=20,n;void dfs(int k){ if(!cnt) return; if(ve.size()==n) { cnt--; for(int i=0;i<n;i++) cout<<ve[i]; puts("")..原创 2022-03-17 10:30:45 · 291 阅读 · 0 评论 -
143. 最大异或对【贪心 trie】
贪心,尽可能走不同的路。#include<bits/stdc++.h>using namespace std;const int N=1e5+10;typedef long long int LL;int son[N*31][2],idx;int a[N],n;void insert(int x){ int p=0; for(int i=30;i>=0;i--) { int u=x>>i&1; i.原创 2022-03-17 10:31:00 · 185 阅读 · 0 评论 -
142. 前缀统计【trie】
基础的trie树题#include<bits/stdc++.h>using namespace std;const int N=1e6+10;int son[N][26],cnt[N],idx;int n,m;void insert(string s){ int p=0; for(int i=0;i<s.size();i++) { int u=s[i]-'a'; if(!son[p][u]) son[p][u]=++i.原创 2022-03-16 20:38:10 · 277 阅读 · 0 评论 -
138. 兔子与兔子【字符串哈希】
很基础的字符串哈希#include<bits/stdc++.h>using namespace std;typedef unsigned long long int ull;const int N=1e6+10;const int M=233;ull base[N],h[N],n;string s;void init(){ base[0]=1; for(int i=1;i<N;i++) base[i]=base[i-1]*M;}ull get(int.原创 2022-03-16 16:57:38 · 219 阅读 · 0 评论 -
132. 小组队列【队列 模拟】
#include<bits/stdc++.h>using namespace std;const int N=1e4+10;int t,id,k;char op[100];int main(void){ while(scanf("%d",&t),t) { k++; map<int,int>mp,st; deque<int>q[N],Q; //q[i]存的是每个小队的人员.原创 2022-03-16 10:34:09 · 261 阅读 · 0 评论 -
145. 超市【小根堆 贪心】
将商品按照时间从小到大排序。如果说此时物品的时间小于堆内的数量。说明堆内有几个物品是要过期的。那么我们用小根堆来维护,直接取最小的删除即可。#include<bits/stdc++.h>using namespace std;typedef pair<int,int> PII;int n;int main(void){ while(cin>>n) { vector<PII>ve; for(int .原创 2022-03-16 09:38:10 · 228 阅读 · 0 评论 -
126. 最大的和【思维 前缀和】
很容易的想到,用二维前缀和,暴力的4层for枚举左上角和右下角的下标。这样肯定会超时。我们不妨先考虑一维的情况,一个数组,如何求最大的矩形。这是一个很简单的DPf[i]=max(f[i-1],0)+a[i] f[i] 表示以i结尾的最大值 最后以所有结尾的取一个max就是结果这时候我们就可以借助列的前缀和,我们通过枚举上下边界,将一个个等高列的矩阵当成一个属数,这样就可以按照刚才一维的方法求解。此时是3层的for,降了一维 。#include<bits/stdc++.h>us.原创 2022-03-16 00:04:18 · 453 阅读 · 0 评论 -
116. 飞行员兄弟【二进制枚举】
二进制枚举即可,需要注意的是,这道题和费解的开关还是有不同点的。费解的开关枚举第一行就行了,因为它有依赖关系的。而这个是一个十字形,无那种关系。故直接暴力枚举邓按不按的所有情况即可。#include<bits/stdc++.h>using namespace std;typedef pair<int,int> PII;string a[10],b[15];char get(char c){ if(c=='-') return '+'; if(c=='.原创 2022-03-15 23:44:57 · 246 阅读 · 0 评论 -
154. 滑动窗口【单调队列】
#include<bits/stdc++.h>using namespace std;const int N=1e6+10;int a[N],n,k;int main(void){ cin>>n>>k; deque<int>q; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) { if(q.size()&am.原创 2022-03-15 13:59:54 · 95 阅读 · 0 评论 -
107. 超快速排序【归并 / 逆序对的数量】
#include<bits/stdc++.h>using namespace std;const int N=1e5*5+10;int a[N],b[N],n;long long int ans;void merge_sort(int l,int r){ if(l>=r) return; int mid=l+r>>1; merge_sort(l,mid),merge_sort(mid+1,r); int i=l,j=mid+1,k=.原创 2022-03-15 10:26:54 · 121 阅读 · 0 评论 -
106. 动态中位数【经典 / 对顶堆】
用对顶堆来维护。一个大根堆,一个小根堆。大根堆存前一半的数据,小根堆存后一半的数据。需要满足这样的一个条件:大根堆最大的数<=小根堆最小的数大根堆的数量最多比小根堆的数量多1,这样大根堆的堆顶就是中位数#include<bits/stdc++.h>using namespace std;int t,id,n;int main(void){ cin>>t; while(t--) { cin>>id>.原创 2022-03-15 10:02:56 · 226 阅读 · 0 评论 -
104. 货仓选址【贪心】
#include<bits/stdc++.h>using namespace std;const int N=1e5+10;int a[N],n,sum;int main(void){ cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); int temp=a[n/2]; for(int i=0;i<n;i++) sum+=abs(a[i]-temp); .原创 2022-03-15 09:27:38 · 318 阅读 · 0 评论 -
103. 电影【多关键字排序】
#include<bits/stdc++.h>using namespace std;const int N=1e5*2+10;map<int,int>mp;int n,m,a[N],b[N],c[N];struct node{int id,x,y;};bool cmp(node a,node b){ if(a.x!=b.x) return a.x<b.x; return a.y<b.y;}vector<node>ve;i.原创 2022-03-15 09:12:28 · 474 阅读 · 0 评论 -
102. 最佳牛围栏【二分 / 思维 不错】
题目的意思就是说,选一个大于等于F的窗口使其平均值最大。那么求去掉平均值后的前缀和。故如果存在一个大于等于F的区间使得 s[r]-s[l-1]>=0 说明就是存在的#include<bits/stdc++.h>using namespace std;const int N=1e5+10;double a[N],s[N];int n,m;bool check(double avg){ for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i.原创 2022-03-14 22:35:03 · 324 阅读 · 0 评论 -
101. 最高的牛【差分 思维】
分析后发现,不会重叠,故都是互相嵌套的这种方式。我们可以初始化,所有的身高都是最大的身高,对于每个区间。区间内的数减1。需要注意的是需要去重,避免重复减。#include<bits/stdc++.h>using namespace std;const int N=1e5+10;int a[N],n,m,p,h;void add(int l,int r,int c){ a[l]+=c; a[r+1]-=c;}vector<pair<int,int..原创 2022-03-14 15:26:14 · 240 阅读 · 0 评论 -
99. 激光炸弹【二维前缀和】
#include<bits/stdc++.h>using namespace std;const int N=5010;int a[N][N],n,r;int main(void){ cin>>n>>r; r=min(r,5000); while(n--) { int x,y,w; cin>>x>>y>>w; a[x+1][y+1]+=w; } .原创 2022-03-14 14:59:42 · 193 阅读 · 0 评论 -
100. 增减序列【差分 / 思维】
本题考察的是差分的思想。设 b[i]=a[i]-a[i-1]因为我们要想让其所有的数字都相等。故即b[2],b[3].......b[n]都得为0才行。此时数组所有的数的值都是b[1]。因为我们的差分操作是每次选两值,让其一个加1,一个减1,基于贪心的思想正负数相互结合。剩下的即为同符号的数。设b[2]…b[n]中正数的和为sum1,负数的和为sum2故最少的操作次数就是max( sum1, abs(sum2) )那么结果的种类为,其实结果的种类就是b[1]的取值有多少个,可以得出有ab.原创 2022-03-14 14:58:05 · 253 阅读 · 0 评论 -
96. 奇怪的汉诺塔【递推】
这是一道很经典的问题。先看3个塔的情况需要注意的是,这里的汉诺塔移动并无只可以移动到相邻塔的需求。即可以直接从A移到C。设d[i]表示将i个盘子从这里移到其他除它之外塔的步数 ,总塔的数量为3故d[i]=d[i-1]+d[i-1]+1 即将i-1个盘子移到B,将i号盘子移动C,再将i-1个盘子从B移到C接下来分析4个塔的情况设f[i]表示将i个盘子从这里移到其他除它之外塔的步数,总塔的数量为4f[i]=min(f[i],f[j]+f[j]+d[i-j]) 将j个盘子移到一个柱子,此时的.原创 2022-03-14 14:40:21 · 249 阅读 · 0 评论 -
95. 费解的开关【二级制枚举】
二进制枚举第一行的操作状态。#include<bits/stdc++.h>using namespace std;const int N=30;char a[N][N],b[N][N];int n,ans;int dx[5]={0,-1,0,0,1};int dy[5]={0,0,-1,1,0};char get(char c){ if(c=='0') return '1'; else return '0';}void solve(int x,int y).原创 2022-03-14 13:22:27 · 170 阅读 · 0 评论 -
递归实现【指数型 / 组合型 / 排列型】枚举
92. 递归实现指数型枚举#include<bits/stdc++.h>using namespace std;const int N=20;int a[N],n;void dfs(int index){ if(index==n+1) { for(int i=1;i<=n;i++) if(a[i]) cout<<i<<" "; puts(""); return; } a[原创 2022-03-14 10:45:29 · 196 阅读 · 0 评论