第三周 jnuacm

分治复习

[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


牛牛与后缀表达式

中缀后缀表达式

后缀表达式_星辰浩宇的博客-CSDN博客_后缀表达式

知道概念与知道用栈怎么做

例题登录—专业IT笔试面试备考平台_牛客网

"1#1#+"

以#分割数字,其他后缀基础

关键是getchar一个一个转换

queue

P2827 [NOIP2016 提高组] 蚯蚓

关键发现可以用queue代替priority_queue时间上节省很多,因为内部单调性

根据输入输出以及n、m的数据范围可以知道,需要在每秒进行切割时找出当前最大值,这时你就会发现枚举堆、单调队列等查找/维护最大值的方法是超时的。这时就诞生了队列三兄弟q1、q2q3,如果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(双端队列)

登录—专业IT笔试面试备考平台_牛客网

简单数据结构

题意

对一个容器进行一系列操作,这题题目有点问题,操作说明多了个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());
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值