目录
第几天(简单计算)
明码(STL专题之bitset)
这一个题的意思就是把题目中所给的数字变成二进制的码来表示,然后每两个数字的码是在一排的.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long LL;
const int Max_n=100005;
int main(){
/* int n,m;
while(~scanf("%d%d",&n,&m)){
bitset<8>x;
x=n;
for(int i=7;i>=0;i--){
if(x[i]) printf("1");
else printf(" ");
}
x=m;
for(int i=7;i>=0;i--){
if(x[i]) printf("1");
else printf(" ");
}
printf("\n");
}*/
//上面的显示的是:九的九次方等于多少?
printf("%.0lf",pow(9,9)); //387420489
return 0;
}
乘积尾零(思维,简单计算)
找0的个数实际上就是找2和5的数量.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long LL;
const int Max_n=30;
int a[Max_n];
int main() {
for(int i=1;i<=100;i++)
scanf("%d",&a[i]);
int num1=0;
int num2=0;
for(int i=1;i<=100;i++){
int x=a[i];
while(x%2==0&&x){
x/=2;
num1++;
}
while(x%5==0&&x){
x/=5;
num2++;
}
}
printf("%d\n",num1>num2?num2:num1);//31
return 0;
}
快速排序(找第k小的数)
代码的大概意思就是先随机生成一个数,把比这个小的都放在它的左边,比它大的数都放在右边,这个数如果是第k小的就返回,如果小于k就再向右半部分,此时就不是第k小的了,否则就向左边去找第k小的数.`
递增三元组(STL专题之二分的应用)
这题不好想到的就是遍历b,如果遍历a复杂度最多降到O(nlogn).
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int Max_n=100005;
int a[Max_n],b[Max_n],c[Max_n];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
sort(a+1,a+1+n);
sort(c+1,c+1+n);
LL ans=0;
for(int i=1;i<=n;i++){
int index1=lower_bound(a+1,a+1+n,b[i])-a;
int index2=upper_bound(c+1,c+1+n,b[i])-c;
ans+=1LL*(index1-1)*(n-index2+1);
}
printf("%lld\n",ans);
return 0;
}
螺旋折线(思维,数学)
把每一圈都补成一个正方形,然后讨论点落在四个方向上的情况.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long LL;
const int Max_n=100005;
int f(int x,int y,int n){
if(x==-n){
if(y==-n)
return 8*n;//n*2*4;
return y+n;//1+(y+n-1);
}
if(y==n){
return 3*n+x;//1+2*n-1+x+n;
}
if(x==n){
return 5*n-y;//1+2*n-1+2*n+n-y;
}
if(y==-n){
return 7*n-x;//1+2*n-1+2*n+2*n+n-x;
}
}
int main(){
int x,y;
scanf("%d%d",&x,&y);
int n=max(abs(x),abs(y));
LL ans=1LL*n*(n-1)*4+f(x,y,n);
printf("%lld\n",ans);
return 0;
}
日志统计(尺取法)
- 首先我们先对每个id在哪个时间收到的赞全部保存在一个vector中,相当于一个邻接表.
- 保存完了以后我们先遍历每一个id
- 判断某个id在[T,T+D)内是否是热帖
- 先判断此id对应的赞一共有多少个,也就是id对应的长度,如果小于k直接返回false,
如果大于k可能有满足条件的区间,我们就对这个id对应的ts进行排序。 - 对于满足情况的时候,我们可以先从第一个时间开始,如果赞没有k个右指针右移,cnt++
如果够了k个,我们就需要判断这些时间间隔是否在D内,如果在就返回true.如果不
在D内,说明时间间隔需要缩短,此时左指针左移,cnt--.
- 先判断此id对应的赞一共有多少个,也就是id对应的长度,如果小于k直接返回false,
- 如果是热帖就放入数组中,否则继续遍历id,直到结束为止.
我们需要明确的是:v[i]里面的一个数就代表一个赞.
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int Max_n=1005;
int ans[Max_n],n,d,k;;//保存符合条件的id
vector<int>v[Max_n];
bool judge(int id){
int len=v[id].size();
if(len<k) return false;
sort(v[id].begin(),v[id].end());//按照时间从小到大排序
int l=0,r=0;
int cnt=0;//表示目前得到的赞.
while(l<=r&&r<len){//某个区间,并且右端点不能超过边界.
cnt++;//如果上一步cnt<k,那么我们r++之后cnt是要加1的.
//(此时一个时间就代表一个赞)如果我们上一步是没有找到
//合适的区间,l++,cnt--因为此时我们的赞已经固定在k了,
//所以我们需要cnt++(增加时间间隔)
if(cnt>=k){//此时赞是够的,只需要在看时间段是否符合就行.
if(v[id][r]-v[id][l]<d) return true;
else{//此时间间隔不满足说明左端点需要右移(缩短间隔)
l++;
cnt--;
}
}
r++;//赞不够我们增加赞,如果是因为时间间隔我们需要右移左端点
//(因为此时我们已经将赞固定的k个了,再往后遍历,删除一个就要增加一个)
}
return false;//最后没有找到合适的时间间隔
}
int main(){
scanf("%d%d%d",&n,&d,&k);
while(n--){
int id,ts;
scanf("%d%d",&ts,&id);
v[id].push_back(ts);
}
int num=0;
for(int i=1;i<=Max_n;i++){
if(judge(i)){
ans[++num]=i;
}
}
for(int i=1;i<=num;i++)
printf("%d\n",ans[i]);
return 0;
}
全球变暖(dfs&连通块)
此题有一个坑点,就是让求有多少岛屿被完全淹没,而不是最终还剩下多少岛屿.
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
typedef long long LL;
const int Max_n=1005;
char a[Max_n][Max_n];
int vis[Max_n][Max_n],n,vis1[Max_n][Max_n];
int net[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
set<char>s;
bool judge_border(int x,int y){
if(x<1||x>n||y<1||y>n)
return false;
return true;
}
void dfs(int x,int y,int color){//标记连通块
a[x][y]=color;
for(int k=0;k<4;k++){
int tx=x+net[k][0];
int ty=y+net[k][1];
if(judge_border(tx,ty)&&!vis[tx][ty]&&a[tx][ty]=='#'){
vis[tx][ty]=1;
dfs(tx,ty,color);
}
}
return ;
}
int main(){
char cnt='0';
scanf("%d",&n);
getchar();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf(" %c",&a[i][j]);
for(int i=1;i<=n;i++){//求连通块并且标记
for(int j=1;j<=n;j++){
if(a[i][j]=='#'){
cnt++;
dfs(i,j,cnt);
}
}
}
/* for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%c",a[i][j]);
if(j==n) printf("\n");
}
}*/
for(int i=1;i<=n;i++){//按照要求淹没陆地
for(int j=1;j<=n;j++){
if(a[i][j]!='.'){
for(int k=0;k<4;k++){
int tx=i+net[k][0];
int ty=j+net[k][1];
if(judge_border(tx,ty)&&a[tx][ty]=='.'){//一个陆地旁边有海洋就被淹没
vis1[i][j]=1;
break;
}
}
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(vis1[i][j]) a[i][j]='.';
/*for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%c",a[i][j]);
if(j==n) printf("\n");
}
}
*/
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]!='.') s.insert(a[i][j]);
printf("%d\n",cnt-'0'-s.size());
return 0;
}