st

2019牛客全国多校第八场A题 All-one Matrices(单调栈)

自闭症网瘾萝莉.ら 提交于 2019-11-27 00:31:02
题意:让你找最大不可扩展全1子矩阵的数量; 题解:考虑枚举每一行为全1子矩阵的的底,然后从左到右枚举;up[i][j]:表示(i,j)这个位置向上可扩展多少,同时还有记录每个位置(i,j)向左最多可扩展到哪个位置pos; 用单调栈维护一个递增的{up[i][j],pos},如果当st.top.first>up[i][j]时,表示栈顶的元素最右可扩展到j-1; lzero:表示下一行最右0所在位置,如果st.top.second<=lzero则表示该栈顶所表示矩阵不可再往下扩展,则对答案贡献1; 参考代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; #define pii pair<int,int> #define mkp make_pair const int maxn=3010; char s[maxn]; int n,m,ans,up[maxn][maxn],num[maxn][maxn]; stack<pii> st; int main() { scanf("%d%d",&n,&m); ans=0; for(int i=1;i<=n;++i) { scanf("%s",s+1); for(int j=1;j<=m;++j) { if((num[i][j]=s[j]-'0')) up[i

强联通分量,缩点

梦想与她 提交于 2019-11-27 00:29:45
没有用的话qaq : Ummmm…图论的大部分知识本来早就有学过,只是一直没有写成博文来梳理,但既然上了qbxt DP图论就写一篇来总结下, 主要是来听DP的,但…由于太菜的原因,DP听得天花乱坠QWQ 一,基础知识篇 1,强连通:如果有两个点u和v,如果u能到达v,v也能到达u,就称u和v是强连通的。 2,强连通分量:有向图极大的强连通子图。 3,强连通图:有向图中任意两个顶点都强连通的图称为强连通图。 4,缩点:将所有的强连通分量都缩成一个点,有向图缩点会形成一个DAG 比如上图中,1和4可以互相到达,我们称1和4强连通。 1,2,3,4构成了一个极大强连通子图(即不存在一个包含1,2,3,4但仍比1,2,3,4构成的强连通子图还大的图),1,2,3,4构成一个强连通分量。 二,找寻强连通分量的方法 1,Kosaraju算法 :基于两次DFS的有向图强连通子图算法。 算法的主要思想是建一个正着的图,再建一个反着的图,先dfs遍历正向图,记下完成遍历的顺序,记住是完成遍历的顺序而不是遍历的顺序,比如上图 遍历的顺序是1-2-4-6-3-5 完成遍历的顺序是 6-4-2-5-3-1,然后再用返图按完成遍历的顺序取最后一个完成访问的节点开始dfs,每dfs一遍证明有一个强连通分量。 一般求取强连通分量运用下一种方法较多,此种方法博主认为OI中应用较少 代码实现 inline void

机试题目中的文件操作

烈酒焚心 提交于 2019-11-27 00:24:15
参考网址 头文件 #include <fstream> 以写模式打开文件 ofstream out("sf1.txt"); 以读方式打开文件 ifstream in("sf1.txt"); 题目实例 从键盘输入4个学生的数据(包括姓名、年龄和成绩),并存放在文件sf1上。从该文件读出这些数据,按成绩从高到底排序,并输出其中成绩次高者的所有数据。 #include<iostream> #include<fstream> #include<algorithm> using namespace std; struct Student { char name[50]; int age; int score; }st[4]; bool cmp(Student a, Student b) { return a.score < b.score; } int main() { Student s; ofstream out("sf1.txt"); cout << "请输入四名学生的姓名、年龄、成绩:" << endl; for (int i = 0; i < 4; i++) { cin >> s.name >> s.age >> s.score; out << s.name << " " << s.age << " " << s.score << endl; } ifstream in("sf1

RMQ问题【模板】

a 夏天 提交于 2019-11-27 00:19:45
概念 RMQ 是英文 Range Maximum/Minimum Query 的缩写,表示区间最大(最小)值。 解决 RMQ 问题的主要方法有两种,分别是 ST 表和线段树。本文主要讲 ST 表。 ST表 $ST$ 表,即 $Sparse-Table$ 算法,它预处理的时间是 $O(nlogn)$,但是查询时间只需要 $O(1)$,且常数非常小。但是不支持修改操作。最重要的是,这个算法非常好写,并且不容易出错。 $ST$ 表是基于倍增思想,令 $d(i, j)$ 表示从 $i$ 开始的,长度为 $2^j$的一段元素中的最小值,则可以用推递的方式计算 $d(i, j)$:$d(i, j) = max\{d(i,j-1), d(i + 2^{j-1}, j-1) \}$,$f[i][0] = a[i]$,即把待查询区间平均分成了两部分。 注意 $2^j \leq n$,因此 $d$ 数组中的元素个数不超过 $n log n$,而每一项都可以在常数时间内计算完成,故总时间为 $O(n log n)$。 来源: https://www.cnblogs.com/lfri/p/11336397.html

P3865 【模板】ST表

拈花ヽ惹草 提交于 2019-11-27 00:05:46
----------------------------------- 链接: P3865 ----------------------------------- st表是一个用来解决RMQ问题的表 st表是一个二维数组,表示的是i~i+2^j-1范围的最值 (这东西和区间DP好像) ---------------------------------- 初始化: 因为2^0=1; 所以说st[i][0]存的就是i~i范围的最值(就是他自己) for(int i=1;i<=n;++i){ cin>>st[i][0]; } 初始化 ---------------------------------- 建立: 我们维护的是长度为2的整数 幂长的区间 对于任何一个区间,我们考虑把他平分成两部分 例如对于st[i][j],我们把它分成st[i][j-1]和st[i+(1<<(j-1)][j-1]两部分,即为分成一半 然后取他们的最值就行了 for(int j=1;j<=21;j++) for(int i=1;i+(1<<j)-1<=n;++i) st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); 建立 ----------------------------- 查询: 我们查询的区间长度当然不会全是2的整数次幂 然而我们又不能查大了(越界)

CodeForces Round #565 Div.3

て烟熏妆下的殇ゞ 提交于 2019-11-26 23:54:08
A. Divide it! #include <bits/stdc++.h> using namespace std; int N; map<long long, int> mp; void init() { mp.clear(); long long u[62]; u[1] = 2; mp[2] = 1; for(int i = 2; i <= 62; i ++) { u[i] = 2 * u[i - 1]; mp[u[i]] = i; } } int main() { scanf("%d", &N); init(); while(N --) { long long x; scanf("%lld", &x); long long ans = 0; if(x == 1) ans = 0; else { while(x % 3 == 0) { x /= 3; x *= 2; ans ++; } while(x % 5 == 0) { x /= 5; x *= 4; ans ++; } if(!mp[x]) ans = -1; else ans += mp[x]; } printf("%lld\n", ans); } return 0; } View Code B. Merge it! #include <bits/stdc++.h> using namespace std;

Knight Moves

允我心安 提交于 2019-11-26 22:26:47
Problem Description A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy. Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part. Your job is to write a program that takes two

牛客多校第八场

。_饼干妹妹 提交于 2019-11-26 22:20:27
https://ac.nowcoder.com/acm/contest/888#question B 签到题,代码可真短。 #include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; #define ll long long int maxx[maxn]; int main() { int n; scanf("%d",&n); ll ans=0; ll sum=0; int t; for(int i=1; i<=n; i++) { scanf("%d",&t); sum=sum-maxx[t]+i; maxx[t]=i; ans=ans+sum; } printf("%lld",ans); } View Code G 签到题 #include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; char s[maxn]; int main() { scanf("%s",s+1); int len=strlen(s+1); int ans=0; stack<char> st; for(int i=1; i<=len; i++) { st.push(s[i]); if(st.size()>=3) { char c1=st.top();st.pop

P3295 [SCOI2016]萌萌哒

不羁岁月 提交于 2019-11-26 21:18:32
复制下来全是乱码呢QwQ: 题目传送门 思路: 我们用ST表,f[i,j]表示[i,i+2^j-1]这一段。 那么初始时每一段单独成一个集合。 对于一个限制可以拆成log 份,然后进行集合合并。 然后呢,如果任意ST[s,t]和ST[i,j]属于同一集合,那么ST[s,t-1]与ST[i,j-1]以及ST[s+2^(t-1)-1,t-1]和f[i+2^(j-1)-1,j-1]都应该属于同一集合。 为了满足这个限制,只要最后再一层一层的做,把下一层的合并了即可。 合并注意必须让编号大的合进编号小的里。 统计答案就很简单啦,答案是9*10^(集合个数-1)。 代码: #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010,M=20; const int Mod=1000000007; int n,m,l1,l2,r1,r2,cnt=0; int fa[N*M],S[N][M],sta[N*M]; int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } void merge(int l1,int l2

POJ2019 Cornfields 二维ST表

时光毁灭记忆、已成空白 提交于 2019-11-26 20:35:56
网址: https://vjudge.net/problem/POJ-2019 题意: 给出一个矩阵,求左下角坐标为$(x,y)$,长度为$b$的正方形的包含的数的最大值和最小值。 题解: 一、二维ST表: 一维$ST$表可以快速处理一维$RMQ$问题,这次是二维问题,好,那就上二维$ST$表,构造方法和一维的类似。开一个四维数组,第一维第三维管横行,第二维第四维管纵行即可(反过来也行)。然后处理完之后按照类似于一维$ST$表一样查询,查询四个小矩阵的最值就行,然后取最值,具体看代码。 AC代码: #include <cstdio> #include <cmath> using namespace std; #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) int mat[255][255]; int maxn[255][255][8][8]; int minn[255][255][8][8]; int maxm(int a,int b,int c,int d) { if(a<b) a=b; if(a<c) a=c; if(a<d) a=d; return a; } int minm(int a,int b,int c,int d) { if(a>b) a=b; if(a>c) a=c; if(a>d) a=d;