分治复习
[NOIP2004]FBI树
分到最末尾,重点在后缀表达,用栈后缀表达
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
#include<functional>
#include<stdlib.h>
#include<ctype.h>
#include<sstream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
typedef long long ll;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
char FBI(string s) {
if (s.length() > 1) {
cout << FBI(s.substr(0, s.length() / 2));
cout << FBI(s.substr(s.length() / 2, s.length() / 2));
}
if (s == string(s.length(), '0')) return 'B';
if (s == string(s.length(), '1')) return 'I';
return 'F';
}
int main() {
int n;
string s;
cin >> n >> s;
cout << FBI(s) << endl;
return 0;
}
01分数规划,再运用二分
xiaomi买东西
这里不能按大小排序然后定,因为万一取最后一个价值开支3600/1000,一般就11/3,这样会大量降低到3.6,而取一个体量小的3.5的效果反而好
用二分找
#include<iostream> #include<algorithm> #include<string> #include<string.h> #include<set> #include<functional> #include<stdlib.h> #include<ctype.h> #include<sstream> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> using namespace std; #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //代码预处理区 const int INF = 0x3f3f3f3f; const int MAX = 1e4 + 7; int n, k; int c[MAX], v[MAX]; double w[MAX]; //全局变量区 bool judge(double x) { for (int i = 1; i <= n; i++) w[i] = v[i] - x * c[i]; sort(w + 1, w + 1 + n, greater<double>()); double sm = 0; for (int i = 1; i <= k; i++) sm += w[i]; return sm > 0; } //函数预定义区 int main() { IOS; int T; cin >> T; while (T--) { cin >> n >> k; for (int i = 1; i <= n; i++) cin >> c[i] >> v[i]; double l = 0, r = INF; for (int i = 1; i <= 100; i++) { double mid = (l + r) / 2; if (judge(mid)) l = mid; else r = mid; } cout << (int)r << endl; } return 0; }
只要让剩下来的刚好为0就能满足x
栈
中缀后缀表达式
知道概念与知道用栈怎么做
"1#1#+"
以#分割数字,其他后缀基础
关键是getchar一个一个转换
queue
P2827 [NOIP2016 提高组] 蚯蚓
关键发现可以用queue代替priority_queue时间上节省很多,因为内部单调性
根据输入输出以及n、m的数据范围可以知道,需要在每秒进行切割时找出当前最大值,这时你就会发现枚举和堆、单调队列等查找/维护最大值的方法是超时的。这时就诞生了队列三兄弟q1、q2和q3,如果q1开始时单调递减,每次取出最大值,然后将这个蚯蚓分开,把其中大的一部分压入q2,小的一部分压入q3,显然,此时q1、q2和q3都是单调递减的(所以每次的取出操作就可以是:在q1、q2、q3的队首取出最大的一个)。
这里是三个queue+sort
也可以1个优先队列+2queue
queue<ll> q1,q2,q3; ll getmax(){ //求三个队列中队首元素的最大值 int x1=-(1<<30),x2=x1,x3=x1; if(!q1.empty())x1=q1.front(); if(!q2.empty())x2=q2.front(); if(!q3.empty())x3=q3.front(); if(x1>=x2&&x1>=x3){q1.pop();return x1;} else if(x2>=x1&&x2>=x3){q2.pop();return x2;} q3.pop();return x3; } void put(ll x1,ll x2){ //压入两条新蚯蚓 if(x1<x2){int z=x1;x1=x2;x2=z;} q2.push(x1),q3.push(x2); return; } bool cmp(ll x,ll y){ return x>y; }
这时你会产生一个疑问:怎样让蚯蚓生长呢?
暴力将每次每只蚯蚓的长度加上q是不现实的,那么那两只往负方向移动了一些. 所以可以记录累计加的长度, 有几只没被加的就减去就好了
for(int i=1;i<=m;++i){ int top=ans.top()+sigma;//被切的蚯蚓的长度 ans.pop(); int a1=floor(p*(double)top),a2=top-a1;//被切成的两只的长度 a1-=sigma,a2-=sigma; a1-=q,a2-=q;//需要减去它们俩没加的 ans.push(a1),ans.push(a2);//放回队列 if(i%t==0)printf("%d ",top);//要求输出的第一行 sigma+=q;//累加 }
队列
noip2004合并果子(基础)
#include <iostream> #include <algorithm> #include <queue> using namespace std; int main() { int n; scanf("%d", &n); priority_queue<int, vector<int>, greater < int>> heap; while (n--) { int x; scanf("%d", &x); heap.push(x); } int res = 0; while (heap.size() > 1) { int a = heap.top(); heap.pop(); int b = heap.top(); heap.pop(); res += a + b; heap.push(a + b); } printf("%d\n", res); return 0; }
deque(双端队列)
简单数据结构
题意
对一个容器进行一系列操作,这题题目有点问题,操作说明多了个a
1 从前面插入元素a
2 从前面删除一个元素
3 从后面插入一个元素a
4 从后面删除一个元素
5 将整个容器头尾翻转
6 输出个数和所有元素
7 对所有元素进行从小到大排序
思路
因为要从队头队尾插入删除元素,我们可以用STL中的deque(双端队列)便于操作
这些是deque的一些基本操作:
push_back(x)/push_front(x) //把x压入后/前端 back()/front() //访问(不删除)后/前端元素 pop_back() pop_front() //删除后/前端元素 empty() //判断deque是否空 size() //返回deque的元素数量 clear() //清空deque 支持通过sort(d.begin(),d.end())进行排序。
代码
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) #pragma GCC optimize(3) typedef long long ll; typedef unsigned long long ull; #define pb push_back #define pll pair<ll,ll> #define INF 0x3f3f3f3f const int mod = 1e9+7; const int maxn = 1e5+5; inline ll read(){ ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } deque<int> q; int main(){ int n = read(),m = read(); while(m--){ int op = read(); if(op == 1){ int a = read(); q.push_front(a); } else if(op == 2) q.pop_front(); else if(op == 3){ int a = read(); q.push_back(a); } else if(op == 4) q.pop_back(); else if(op == 5) reverse(q.begin(),q.end());//翻转 else if(op == 6){ cout<<q.size()<<endl; for(int i = 0 ; i < q.size() ; ++i) cout<<q[i]<<" "; cout<<'\n'; } else sort(q.begin(),q.end()); } }