模拟&&排序
模拟
P1003 [NOIP2011 提高组] 铺地毯
一开始就直接暴力超时超内存还很疑惑,现在再看代码确实有点太暴力,二维数组加一个矩形区域都复制,1e4 数据,每个数据xx的区域赋值1e51e5,时间复杂太大啦,都三重循环啦,而且是二维数组用long long 的话开的内存也太大了
题解的思路是,先将地板铺好,再根据这一点的坐标值去倒序寻找地板。那么我们判断一个点是否在矩形中,就可以用这种思路了,确定矩形的左下和右上点即可。
P1067 [NOIP2009 普及组] 多项式输出
这个就是一个简简单单的模拟啦,但越是这种题越要细心注意一些的细节
P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
可以选择列举每一种情况但很没意思,也可以用数组来实现,在准确一点矩阵的思想。一开始还在纠结这个矩阵怎么存的一半是甲对乙的结果另一半是乙对甲的结果,现在发现纠结了个寂寞。就是存储一个人的结果。
这种列举情况的用矩阵来做较容易。
P1563 [NOIP2016 提高组] 玩具谜题
找规律举例一些情况出来很容易发现有四种情况,在当前位置加减相应的数字即可。但这里是圆环里的减需要加上总个数减去步数再模n,圆环里的加直接加上步数模n。
P1042 [NOIP2003 普及组] 乒乓球
乒乓球子很久没打啦。
这个题漏掉了条件,不能轻易忽视题干的任何一句。还有,11分制,21分制是率先到达11,率先达到21,并且两个人要有不小于2的差距。常识
P1179 [NOIP2010 普及组] 数字统计
这个题也是直接模拟就可以,一个入门题。但这样做没意思。记得之前cf补过类似的题,但是直接模拟是不可以的。是找规律。我的记忆只能搜索到这了,我真厉害。具体的忘了怎么分类的了。
将一个数分成个位,十位,百位等等,将个位上的2,加上十位上的2,等等。但就只是计算到这里是不可以的,记得上次就落下了这种情况还是队友给我讲的。
举例:51206
算个位:答案是1~51200中2在个位出现次数+51201-51206中2在个位出现次数
5120×1+1
算十位:答案是1~51200中2在十位出现次数+51201-51206中2在十位出现次数
512×10+0
算百位:答案是1~51000中2在百位出现次数+51001-51206中2在百位出现次数
51×100+7
算千位:答案是1~50000中2在千位出现次数+50001-51206中2在千位出现次数
5×1000+0
算万位:答案是1~51206中2在万位出现次数
#include <bits/stdc++.h>
#define long long ll
using namespace std;
const int N=100000;
//这个题之前做过数据大,根本无法用暴力解决
//记得当时是找规律,但是忘记啦!!好气
int f(int x)
{
int a=x,t=1,s=0;//t表示个位t=1,十位t=10,s记录答案
while(x)
{
s+=x/10*t;
if(x%10>2) s+=t;
if(x%10==2) s+=a%t+1;
//这个地方容易忽略
x/=10;
t*=10;
}
return s;
}
int main()
{
int l,r;
cin>>l>>r;
cout <<f(r)-f(l-1)<<endl;
return 0;
}
poj2388快速排序,还解决求前k大的数,求中间数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
//快速排序有必要再写一下
//可以将其放在两个临时空间
//但也可以就直接在原数组中操作
const int N=10010;
int a[N];
//t为基准数字,i代表大于t的,j代表小于t的
int p(int l,int r)
{
int i=l;
int t=a[r];//最右端
for(int j=l;j<r;j++)
{
if(a[j]<t)//遇到比t小的
{
swap(a[i],a[j]);
i++;
}
}
//最后交换
swap(a[i],a[r]);
return i;
}
void kp(int l,int r)
{
if(l<r)
{
int i=p(l,r);//划分
kp(l,i-1);//分治
kp(i+1,r);
}
}
int main()
{
int n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
kp(1,n);
cout<<a[(n+1)/2]<<endl;
return 0;
}
P2615 [NOIP2015 提高组] 神奇的幻方
简单模拟就可以,但这个题花费的时间最多测试了很长时间,一个if判断语句好气
排序
P1177 【模板】快速排序
除了sort排序还有stl,二分的做法
void qsort(int l,int r)//应用二分思想
{
int mid=a[(l+r)/2];//中间数
int i=l,j=r;
do{
while(a[i]<mid) i++;//查找左半部分比中间数大的数
while(a[j]>mid) j--;//查找右半部分比中间数小的数
if(i<=j)//如果有一组不满足排序条件(左小右大)的数
{
swap(a[i],a[j]);//交换
i++;
j--;
}
}while(i<=j);//这里注意要有=
if(l<j) qsort(l,j);//递归搜索左半部分
if(i<r) qsort(i,r);//递归搜索右半部分
}
P1908 逆序对
归并排序和树状数组做
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=500010;
ll a[N],b[N],cnt,n;
//归并排序
//归并排序一共分为三个步骤分解,解决,合并
void m(int l,int mid,int r)
{
ll i=l,j=mid+1,t=0;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])
{
b[t++]=a[j++];
cnt+=mid-i+1;
}else
{
b[t++]=a[i++];
}
}
//然后处理两个部分剩下的元素
while(i<=mid) b[t++]=a[i++];
while(j<=r) b[t++]=a[j++];
for(i=0;i<t;i++) a[i+l]=b[i];
}
void msort(int l,int r)
{
if(l<r)
{
ll mid=(l+r)/2;//平均分为两个
msort(l,mid);
msort(mid+1,r);
m(l,mid,r);//合并
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
msort(0,n-1);
cout<<cnt<<endl;
return 0;
}
周六下午在自习室的时候就突然想到,在大学最开心的事莫过于整个周末在一间安静的自习室一台电脑,一个热点,一打演算纸和一支笔,一个水杯,一袋面包。如果整个周末都有条件这样度过会超级开心。
就是现在水平太low了,好着急