基础算法
图一乐图一乐
这个作者很懒,什么都没留下…
展开
-
牛客网,和与或(状态压缩)
题意: 给你一个数组R,包含N个元素,求有多少满足条件的序列A使得 0 ≤ A[i] ≤ R[i] A[0]+A[1]+…+A[N-1]=A[0] or A[1]… or A[N-1] 思路:等式成立的前提是如果某一二进制位上存在1,那必定是由N个元素中某一个提供,除这个数外的其他数,这一位上只能是0。 #include<bits/stdc++.h> #define f(i,a,b) for( int i=a;i<=b;++i) #define ff(i,a,b) for( int i=a原创 2020-11-17 11:29:15 · 247 阅读 · 1 评论 -
2020暑期牛客第六场 K-Bag(思维,前缀)
收获:对于一个长度为k的区间是否存在[L,L+k−1][L,L+k-1][L,L+k−1]的所有数字,可以用区间和和区间异或和来判别。 思路:对于前后残缺的区间可以预处理出前后缀中不同数字的个数,然后枚举分割点,对于完整的区间用区间和和区间异或和判断。 ll a[N], XOR[N], SUM[N]; ll n, k, sum, Xor; int cot1[N], cot2[N]; void x_x() { unordered_map<ll, int> mp; cot1[0] = cot2[原创 2020-07-29 12:44:14 · 153 阅读 · 0 评论 -
C. Skyscrapers(离散化)
int r[1010], c[1010]; int a[1010][1010]; int rr[1010][1010], cc[1010][1010]; int main() { //freopen("in.txt", "r", stdin); int n, m; cin >> n >> m; f(i, 1, n)f(j, 1, m)scanf("%d", &a[i][j]); f(i, 1, n) { f(j, 1, m)rr[i][j] = a[i][j]原创 2020-07-19 15:59:10 · 174 阅读 · 0 评论 -
C2 - Skyscrapers (hard version)(单调栈)
思路:从左到右求一遍单调栈,,每次维护前缀,再倒着来一次。 int a[N]; ll p[N], fp[N]; int main() { //freopen("in.txt", "r", stdin); int n; while (cin >> n) { f(i, 1, n)scanf("%d", &a[i]); stack<int> st; f(i, 1, n)//从左到右求一遍单调栈,递增 { while (!st.empty() &原创 2020-07-19 12:19:33 · 202 阅读 · 0 评论 -
B. DZY Loves Modification(优先队列加枚举)
思路:贪贪贪! ll r[N], c[N]; multiset<ll> str, stc; int main() { //freopen("in.txt", "r", stdin); int n, m, k, p,x; while (cin >> n >> m >> k >> p) { f(i, 1, n) { f(j, 1, m)//记录每行每列的和 { scanf("%d", &x); r[i原创 2020-07-15 22:02:59 · 139 阅读 · 0 评论 -
C. Painting Fence(递归)
int a[N]; pii find(int l, int r) { pii ans = { 2e9,0 }; f(i, l, r) { ans.first = min(ans.first, a[i]); ans.second = max(ans.second, a[i]); } return ans; } int get(int l, int r) { pii val = find(l, r); if (val.first == 0)return 0; if (val.first == val原创 2020-07-15 21:07:29 · 387 阅读 · 0 评论 -
2020暑期第二场 Fake Maxpooling(单调队列)
const int N = 5005; int t; struct node { ll idx, w; }q[N]; vector<int> v[N]; int main() { //freopen("in.txt", "r", stdin); int n, m, k; cin >> n >> m >> k; //f(i, 1, n)f(j, 1, m)mp[i][j] = i * j / gcd(i, j);原创 2020-07-14 17:16:05 · 92 阅读 · 0 评论 -
E. Compress Words(前后缀hash)
#include<bits/stdc++.h> #define f(i,a,b) for(register int i=a;i<=b;++i) #define ff(i,a,b) for(register int i=a;i>=b;--i) #define debug(x) cerr << #x << " : " << x << " " << endl using namespace std; typedef long lo原创 2020-07-14 10:53:50 · 292 阅读 · 0 评论 -
atcoder-D - Xor Sum 4(位运算+组合数学思想)
思路:统计二进制上每一位上1出现的次数。然后异或,考虑每一位上0和1的组合次数,乘上这位的数值。 int a[65]; int main() { //freopen("in.txt", "r", stdin); int n; ll x; while (cin >> n) { f(i, 1, n) { scanf("%lld", &x); f(j, 0, 60) { if (x >> j & 1)a[j]++; }原创 2020-07-12 10:40:12 · 264 阅读 · 0 评论 -
atcoder-C - HonestOrUnkind2(二进制枚举)
思路:N=15这个信息就很敏感,二进制枚举参加的人,对他们的话进行判断,看看是否出现矛盾,无矛盾则更新答案。 vector<pii> a[20]; int main() { //freopen("in.txt", "r", stdin); int n; while (cin >> n) { int x, y, m; f(i, 1, n) { scanf("%d", &m); while (m--) { scanf("%d%d",原创 2020-07-12 10:19:42 · 245 阅读 · 0 评论 -
三分板子
ll ef(ll l,ll r)//三分 { while(r - l > eps) //保证精度,最好是k+2位精度哦! { ll lmid=l+(r-l)/3,rmid=r-(r-l)/3; if(check(lmid)<=check(rmid)) l=lmid; else r=rmid; } return r; }原创 2020-07-08 22:10:29 · 301 阅读 · 0 评论 -
D. Vasya and Triangle(构造)
int main() //构造 { //freopen("in.txt", "r", stdin); ll m, n, k; while (cin >> n >> m >> k) { if (2 * n*m%k != 0) { puts("NO");continue; } ll d = gcd(2 * m, k); puts("YES"); cout << "0 0" << endl; if (d == 1)//n%k=原创 2020-07-07 16:03:12 · 189 阅读 · 0 评论 -
C - Phone Numbers(思维)
思路:对于n<k,必定是s+(k-n)个min字符,对于n>=k,贪心取,更改最后一个不为max字符的字符,将它改成大于最小的字符,并把后的字符全部输出min字符。 int main() { //freopen("in.txt", "r", stdin); int n, k; while (cin >> n >> k) { string s; cin >> s; map<char, int> mp; for (auto I原创 2020-07-06 21:44:20 · 168 阅读 · 0 评论 -
经商(并查集+01背包)
思路:先并查集求出和1号在同一个连通块的的人,然后进行01背包。 const int N = 1e5 + 5; int a[N], b[N], dp[N]; int fa[N]; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } int t; int main() { //freopen("in.txt", "r", stdin); cin >> t; while (t--) { int n, m, c原创 2020-07-02 13:41:09 · 107 阅读 · 0 评论 -
AcWing 102. 最佳牛围栏(二分答案)
题意:给一个长度为n的序列,选取一段大于等于k的子序列,求可能子序列的最大平均值。 思路:首先答案是可以二分的,每次二分去判断是否有可行解。 然后就是怎么写二分的check了,区间的平均数大于当前所要判断的平均值等价于区间每个数减去平均值后区间和大于0,然后写个双指针,维护前序最小的前缀。 int n, len; int a[N]; double sum[N]; bool check(double now) { f(i, 1, n)sum[i] = sum[i - 1] + a[i] - now;//区间原创 2020-05-14 21:17:02 · 286 阅读 · 0 评论 -
AcWing 100. 增减序列(差分,贪心)
题意:给一个数组a,每次可以a的任意区间[l,r]加减1,求最少通过几次操作使得数组a中所有元素大小相等,并输出可能的最小方案次数。 思路:区间加减数,先考虑构造差分数组。 构造差分数组b使得: a[1]=b[1]; a[2]=b[1]+b[2]; a[3]=b[1]+b[2]+b[3]; … 要使得最后a中所有元素相等,那么要使得b中b[i](2<=i<=n)都为0, 而了解过差分的性质后可知:对a[l,r]的元素+1等价于差分数组中b[l]+1,b[r]-1。 那么贪心的思路来了,如果要以快原创 2020-05-14 20:03:40 · 359 阅读 · 0 评论 -
AcWing 95. 费解的开关(枚举,递推)
思路:枚举第一行每个位置按与不按,得到32种第一行的情况,对于每种情况,递推(上一行的是0,那正下方一行同个位置需要点亮),最后一行判断是不是点亮,判断当前方案是否有解,有解则维护最小解。 char mp[6][6]; char nw[6][6]; int dx[] = {1,0,-1,0,0}; int dy[] = {0,1,0,-1,0}; void change(int x,int y) { f(i, 0, 4) { int nx = x + dx[i], ny = y + dy[i];原创 2020-05-14 15:46:37 · 176 阅读 · 0 评论 -
C. Save the Nature(贪心,二分)
题意:对于如果卖出的次序是a的倍数,那么可以获得当前这张票的x%价值,卖出次序是b的倍数,那么可以获得当前这张票的y%价值,如果同时是a,b倍数,那么获得这张票的(x+y)%的价值,求至少卖出几张可获得K价值,不能输出-1。 思路:随者卖出票数的增加,可获得报酬的序位在增加,那么在贪心(把大的金额分配给大的倍率)基础上获得的价值是单调递增的,所以二分。 int t; int p[N]; ll n...原创 2020-04-19 19:32:09 · 271 阅读 · 0 评论 -
C. p-binary(bitset)
题意:给出一个32位整数n和p,求最小使用2的幂的个数,使得n = (2^x1 + p) + (2^x2 + p ) + … 思路:先移项成n - p * i = 2^x1 + 2^x2 + 2^x3; 我们可以知道的是一个数n,如果他的二进制中有k个1,那么我们最小可以用k个2的幂数,最多可以用n个2的幂数累加得到它。 然后1e9的大小是32位不到,这里直接枚举n-p*i 32次,求出第一次满足...原创 2020-04-03 09:23:10 · 216 阅读 · 0 评论 -
String HDU - 5672(尺取)
题意:给个字符串,求至少的包含k个不同字符的区间数。 思路:双指针(尺取),维护一个有k个不同字符的区间,答案是以当前区间为前缀的所有区间,当左指针==n-k,退出。 int t; int mp[30]; int main() { cin >> t; string a; while (t--) { int k; cin >> a; scanf("%d",...原创 2020-03-31 08:40:05 · 96 阅读 · 0 评论 -
Graveyard Design POJ - 2100(尺取)
尺取:维护一段连续的区间具有某个性质。 这里维护连续区间元素平方和小于等于n。 vector<int> v[N]; int main() { ll n; while (cin >> n) { ll l = 1, r = 0; ll sum = 0; int cs = 0; while(1) { r++; if (r*r > n)b...原创 2020-03-26 15:09:18 · 179 阅读 · 0 评论 -
Median POJ - 3579(二分法)
题意:给n个数,求所有|ai-aj|的中位数。 思路:看到中位数,应该要敏感的考虑二分。设中位数为x,|ai-aj|=ci, 有1/2的ci大于x,还有1/2的ci小于x,然后不同的aj>ai的对数是1到n的累加,也就是c(n,2),那么二分的check函数找到了。在check中枚举每个ai+x,求大于等于它的aj的个数,累加判断就好了。假如7,那要3个大于,假如6,根据题意也要有3个大于。...原创 2020-03-15 11:51:37 · 155 阅读 · 0 评论 -
Max Sum of Max-K-sub-sequence HDU - 3415(单调队列)
单调队列三步:去尾,删头,维护答案。 去尾:从后往前,把不如要加入的点优秀的点删除。 删头:把不在范围的点出队。 这里要维护[i-m,i)范围内的最小前缀和,这样sum[i]-sum[min]可取得每个位置下的最优答案,然后维护最大。 const int N = 2e5 + 5; int t; int a[N]; int sum[N];//求每个位置的前缀,比较保留哪个位置 int q[N]; ...原创 2020-03-14 18:55:51 · 121 阅读 · 0 评论 -
Drying POJ - 3104(二分)
要把加速器每分钟的贡献看成k-1,1 1 1 k 1 1 k,这样可通过时间来确定具体需要干燥几次。 const int N = 1e5 + 5; int t; int n, k; int a[N]; bool judge(ll mid) { //计算需要干燥几次 这里加速器的效果是真实效果是k-1,因为在自然状态-1/min ll cot = 0; f(i, 1, n) { if ...原创 2020-03-10 21:49:23 · 139 阅读 · 0 评论