DAY 4 基础算法
基础算法
本来今天是要讲枚举暴力还有什么的,没想到老师就说句那种题目就猪国杀,还说只是难打,不是难。。。。
STL(一)set
感觉今天讲了好多,set,单调栈,单调队列,单调栈和单调队列保证了序列的单调性,一般的,凡是找左右第一个比他大或小的大概率是这个东西,原来作业1的奶牛歌声就是这个东西,但不是道为什么我爆力优化过了。。。。
然后就是这题
这题要用set,不用还过不了。。。。
set常用函数
- begin() ,返回set容器的第一个元素
- end() ,返回set容器的最后一个元素
- clear() ,删除set容器中的所有的元素
- empty() ,判断set容器是否为空
- max_size() ,返回set容器可能包含的元素最大个数
- size() ,返回当前set容器中的元素个数
- rbegin ,返回的值和end()相同
- rend() ,返回的值和rbegin()相同
可以这样练下手
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int >s;
s.insert();
s.insert();
s.insert();
s.insert();
cout<<"长度是"<<s.size()<<endl;
cout<<"可能包含元素的最大个数为"<<s.max_size() <<endl;
cout<<"第一个元素是"<< *s.begin()<<endl;
cout<<"最后一个元素是"<<*s.end()<<endl;
s.clear();
if(s.empty())
{
cout<<"空啦!!!!"<<endl;
}
cout<<"长度是"<<s.size()<<endl;
cout<<"可能包含元素的最大个数为"<<s.max_size() <<endl;
}
输出是这样的:
注意如果这样打
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int >s;
s.insert();
s.insert();
s.insert();
s.insert();
cout<<"第一个元素是"<< *s.begin()<<endl;
cout<<"最后一个元素是"<<*s.end()<<endl;
return ;
}
我们可以发现最后一个元素显示还是3.。。
- count() 用来查找set中某个某个键值出现的次数
这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int >s;
s.insert();
s.insert();
s.insert();
s.insert();
cout<<"set 中 1 出现的次数是 :"<<s.count()<<endl;
cout<<"set 中 4 出现的次数是 :"<<s.count()<<endl;
return ;
}
输出应该是这样的
- equal_range() ,返回一对定位器,分别表示第一个大于或等于给定关键值的元素和 第一个大于给定关键值的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于end()的值。
#include <iostream>
#include <set> using namespace std; int main()
{
set<int> s;
set<int>::iterator iter;
for(int i = ; i <= ; ++i)
{
s.insert(i);
}
for(iter = s.begin() ; iter != s.end() ; ++iter)
{
cout<<*iter<<" ";
}
cout<<endl;
pair<set<int>::const_iterator,set<int>::const_iterator> pr;
pr = s.equal_range();
cout<<"第一个大于等于 3 的数是 :"<<*pr.first<<endl;
cout<<"第一个大于 3的数是 : "<<*pr.second<<endl;
return ;
}
输出因该是这样的
- erase(iterator) ,删除定位器iterator指向的值
- erase(first,second),删除定位器first和second之间的值
- erase(key_value),删除键值key_value的值
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> s;
set<int>::const_iterator iter;
set<int>::iterator first;
set<int>::iterator second;
for(int i = ; i <= ; ++i)
{
s.insert(i);
}
//第一种删除
s.erase(s.begin());
//第二种删除
first = s.begin();
second = s.begin();
second++;
second++;
s.erase(first,second);
//第三种删除
s.erase();
cout<<"删除后 set 中元素是 :";
for(iter = s.begin() ; iter != s.end() ; ++iter)
{
cout<<*iter<<" ";
}
cout<<endl;
return ;
return ;
}
输出
- insert(key_value); 将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
- inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.
- lower_bound(key_value) ,返回第一个大于等于key_value的定位器
- upper_bound(key_value),返回最后一个大于key_value的定位器
非常尴尬的发现就算学了这个东西,那题还是不会。。。。。。。
STL(二)bitset
感觉这个东西还挺好用的,也是STL里的一个神器,感觉好多题目都能用,那个三维偏序好像除了CDQ分治,KD——tree,和bitset都能打。。。还是只占一个字符,比单纯的bool,好用不知道多少。
初始化:
#include<iostream>
#include<bitset>
using namespace std;
int main()
{
bitset<> bitset1;//初始化,长度为4,全都是0
bitset<> bitset2();//长度是8,用二进制存12,不足位补0
string s="";
bitset<> bitset3(s);//同上
cout<<bitset1<<endl;
cout<<bitset2<<endl;
cout<<bitset3<<endl;
return ;
}
输出应该是这样的:
另外,bitset只能存0或1,如果有其他的东西会报错,原来char也可以,但不知道为什么会警告,能不用最好还是不用。。。。
一些常见的位运算:
#include<iostream>
#include<bitset>
using namespace std;
int main()
{
bitset<> bitset1(string(""));
bitset<> bitset2(string(""));
cout<<(bitset1^=bitset2)<<endl;//按位异或后将值付给bitset1
cout<<(bitset1&=bitset2)<<endl;//按位与后将值付给bitset1
cout<<(bitset1|=bitset2)<<endl;//按位或后将值付给bitset1
cout<<(bitset1<<=)<<endl;//右移后将值付给bitset1
cout<<(bitset1>>=)<<endl;//左移后将值付给bitset1
cout<<(bitset1==bitset2)<<endl; //假的,返回false(0)
cout<<(bitset1!=bitset2)<<endl;//真的,返回true(1或-1)
cout<<(bitset2&bitset1)<<endl;//左移后将值付给bitset1 ,其他同理
return ;
}
输出应该是这样的:
还可以像数组那样去访问每一位
一些常用的函数:
这正是STL吸引人的主要原因,可以不用手打,但会慢,对于我这样的蒟蒻就完全不会有影响,但也许对于机房旁边的大佬(传送门)就会有很大影响,这会让他AK不了IOI!!!!
#include<iostream>
#include<bitset>
#include<cstdlib>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
bitset<> bitset1(string(""));
cout<<bitset1.count()<<endl;//(count函数用来求bitset中1的位数,foo中共有5个1
cout<<bitset1.size()<<endl;//(size函数用来求bitset的大小,一共有8位
cout<<bitset1.test()<<endl;//(test函数用来查下标处的元素是0还是1,并返回false或true,此处foo[0]为1,返回true
cout<<bitset1.test()<<endl;//(同理,foo[2]为0,返回false
cout<<bitset1.any()<<endl;//(any函数检查bitset中是否有1
cout<<bitset1.none()<<endl;//(none函数检查bitset中是否没有1
cout<<bitset1.all()<<endl;//f(all函数检查bitset中是全部为1
//说明一下:test函数会对下标越界做出检查,而用过数组方式访问的元素则不会,所以用test更安全一些
string s=bitset1.to_string();//将bitset转换成string类型
unsigned long a=bitset1.to_ulong();//将bitset转换成unsigned long类型
cout<<s<<endl;
cout<<a<<endl;
cout<<bitset1.flip()<<endl;//(flip函数传参数时,用于将参数位取反,本行代码将foo下标2处"反转",即0变1,1变0
cout<<bitset1.flip()<<endl;//(flip函数不指定参数时,将bitset每一位全部取反
cout<<bitset1.set()<<endl;//(set函数不指定参数时,将bitset的每一位全部置为1
cout<<bitset1.set(,)<<endl;//(set函数指定两位参数时,将第一参数位的元素置为第二参数的值,本行对foo的操作相当于foo[3]=0
cout<<bitset1.set()<<endl; //(set函数只有一个参数时,将参数下标处置为1
cout<<bitset1.reset()<<endl;//(reset函数传一个参数时将参数下标处置为0
cout<<bitset1.reset()<<endl;//(reset函数不传参数时将bitset的每一位全部置为0
//这些函数同样会检查数组下标,有异常会提示。 return ;
}
贪心:
贪心是个非常有用的东西,有时候没有思路,也不会证明,但乱搞就过了。。。。
bzoj 3668 起床困难综合征(门)
- 从高位到低位枚举每一位,判断是1还是0,位运算各位之间不会影响。
- 保证当前的数不会大于m;
对于0能变为1的两种情况直接变。
0变为的两种情况不予考虑。
代码就非常简单:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5+;
char op[];
long long n,m;
long long t;
long long ans=,ans0=,ans1=0x7fffffff;
int main()
{
//freopen("testdata.in","r",stdin);
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s %lld",op,&t);
if(op[]=='A')
{
ans1&=t;
ans0&=t;
}
else
if(op[]=='O')
{
ans1|=t;
ans0|=t;
}
else
if(op[]=='X')
{
ans1^=t;
ans0^=t;
}
}
for(int i=;i>=;i--)
{
if(ans0&(<<i))
{
ans+=(<<i);
}
else
if((m>=(<<i))&&(ans1&(<<i)))
{
m-=(<<i);
ans+=(<<i);
}
}
cout<<ans<<endl;
return ;
}
BZOJ 2563 阿狸和桃子的游戏(门)
这题可以吧边权平分到两边的点,这样相对大小没变,一减也没变。
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+;
int sum[maxn];
int x,y,z;
int k;
int ans=;
int n,m;
int main()
{
cin>>n>>m;
for(int i=;i<=n;i++)
{
cin>>k;
sum[i]=k<<;
}
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
sum[x]+=z;
sum[y]+=z;
}
sort(sum+,sum++n);
for(int i=n;i>=;i-=)
{
ans+=sum[i]-sum[i-];
}
ans/=;
cout<<ans<<endl;
return ;
}
NOIP 2015 跳石头(还是回淮南的测试里的题目)
- 显然这题这题就是二分还是比较经典的哪一类。
- 二分一个答案,看他是否符合条件。
- 贪心
- 从第二块开始循环(第一块不能搬走,要不然你站哪?)假设现在到了第i块,上一个没搬走的是第J块,如果当前的距离小于ans,就可以直接搬走,要不然就留下来。
- 最后一块不能搬走,要不你最后站哪?
快乐的代码时光(机房考试还有人打了线段树,几千字。。。)
NOIP 2012 DAY2 T2 借教室
- 这题好快乐,暴力拿了50分。。。
- 正解还是二分,二分一个答案,看他能满足到哪一个订单。
- 然后把1到ans的所有订单都扫描一下。
- 可以用差分数组优化一下复杂度。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib> using namespace std; const int maxn=1e6+; int need[maxn];
int sheng[maxn];
int r[maxn];
int l[maxn];
int d1[maxn];
int d2[maxn];
int n,m; int panduan(int x)
{
memset(d2,,sizeof(d2));
for(int i=;i<=x;i++)
{
d2[l[i]]+=d1[i];
d2[r[i]+]-=d1[i];
}
for(int i=;i<=n;i++)
{
need[i]=need[i-]+d2[i];
if(need[i]>sheng[i])
return ;
}
return ;
} int main()
{
memset(d1,,sizeof(d1));
memset(need,,sizeof(need));
memset(sheng,,sizeof(sheng));
memset(l,,sizeof(l));
memset(r,,sizeof(r));
cin>>n>>m;
for(int i=;i<=n;i++)
{
cin>>sheng[i];
}
for(int i=;i<=m;i++)
{
cin>>d1[i]>>l[i]>>r[i];
}
if(panduan(m))
{
cout<<""<<endl;
return ;
}
else
{
int L=,R=m;
while(L<R)
{
int middle=(L+R)/;
if(panduan(middle))
{
L=middle+;
}
else
{
R=middle;
}
}
cout<<"-1"<<endl<<L<<endl;
}
return ;
}
DAY 4 基础算法的更多相关文章
- PHP基础算法
1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++ ...
- 10个经典的C语言面试基础算法及代码
10个经典的C语言面试基础算法及代码作者:码农网 – 小峰 原文地址:http://www.codeceo.com/article/10-c-interview-algorithm.html 算法是一 ...
- Java基础算法集50题
最近因为要准备实习,还有一个蓝桥杯的编程比赛,所以准备加强一下算法这块,然后百度了一下java基础算法,看到的都是那50套题,那就花了差不多三个晚自习的时间吧,大体看了一遍,做了其中的27道题,有一些 ...
- 贝叶斯公式由浅入深大讲解—AI基础算法入门
1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大.而且概率虽然未知,但最起码是一个确定 ...
- 贝叶斯公式由浅入深大讲解—AI基础算法入门【转】
本文转载自:https://www.cnblogs.com/zhoulujun/p/8893393.html 1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生, ...
- java入门学习(3)—循环,选择,基础算法,API概念
1.顺序结构:也就是顺着程序的前后关系,依次执行.2.选择分支:利用if..else , / switch(){case [ 这个必须是常量]:}; / if..else if….. ….else.. ...
- Java - 冒泡排序的基础算法(尚学堂第七章数组)
/** * 冒泡排序的基础算法 */ import java.util.Arrays; public class TestBubbleSort1 { public static void main(S ...
- c/c++面试总结---c语言基础算法总结2
c/c++面试总结---c语言基础算法总结2 算法是程序设计的灵魂,好的程序一定是根据合适的算法编程完成的.所有面试过程中重点在考察应聘者基础算法的掌握程度. 上一篇讲解了5中基础的算法,需要在面试之 ...
- c/c++面试指导---c语言基础算法总结1
c语言基础算法总结 1 初学者学习任何一门编程语言都必须要明确,重点是学习编程方法和编程思路,不是学习语法规则,语法规则是为编程实现提供服务和支持.所以只要认真的掌握了c语言编程方法,在学习其它的语 ...
- ACM基础算法入门及题目列表
对于刚进入大学的计算机类同学来说,算法与程序设计竞赛算是不错的选择,因为我们每天都在解决问题,锻炼着解决问题的能力. 这里以TZOJ题目为例,如果为其他平台题目我会标注出来,同时我的主页也欢迎大家去访 ...
随机推荐
- CountDownLatch源码及Javadoc阅览
/** * A synchronization aid that allows one or more threads to wait until * a set of operations bein ...
- badboy录制脚本
第一步:介绍badboy工具 1.1: 页面功能分析: 1. 界面视图,模拟浏览器,能够进行操作 2. 需要录制脚本的URL 3. 点击运行URL 4. Summary:运行的各指标,响应时间,成功事 ...
- python requests简单接口自动化
get方法 url:显而易见,就是接口的地址url啦 headers:定制请求头(headers),例如:content-type = application/x-www-form-urlencode ...
- postman全局变量设置
1.点击小齿轮进入到变量添加页面,点击Globals添加全局变量 2.输入变量名称和变量值 3.接口中设置变量
- 构造函数语义学——Copy Constructor 篇
构造函数语义学--Copy Constructor 篇 本文主要介绍<深度探索 C++对象模型>之<构造函数语义学>中的 Copy Constructor 构造函数的调用时机 ...
- postman简单介绍
- c#菜单动态合并
说明 在程序中经常使用弹出菜单,并且一个窗体中可以存在多个弹出菜单.开发过MDI窗体的读者可能都知道,当MDI子窗体最大化时,子窗体和主窗体的菜单能够自动的合并.这是如何实现的呢?本例实现了将两个弹出 ...
- 百万年薪python之路 -- HTML基础
一. Web标准 web标准: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web标准规范的分类:结构标准.表现标准.行为标准. 结构:html.表示:c ...
- SpringBoot系列教程之Bean之指定初始化顺序的若干姿势
上一篇博文介绍了@Order注解的常见错误理解,它并不能指定 bean 的加载顺序,那么问题来了,如果我需要指定 bean 的加载顺序,那应该怎么办呢? 本文将介绍几种可行的方式来控制 bean 之间 ...
- Redis备忘(一)
hash: 渐进式rehash:同时查询新旧两个hash,然后在后续定时任务以及hash的子指令中,循序渐进将旧的迁移到新的hash表 Redis应用: 1.分布式锁: 实现1:setnx+expir ...