最近感觉自己有点努力,但是还是不够。总体上看水平还是不够,学的算法也太少,所以这学期要好好加油了!
为了适应以后高强度的比赛,最近连一直不碰的CF也开始刷了。但是让我半夜起来比赛也是不合适啊,所以只可以隔天刷刷玩玩了!
A. Two Bases
题意:给你两个数比较大小,但是数以b进制的形式给出。n表示b进制数的位数,b当然表示进制,接下来的n个数从高位到低位表示每个位的数值。然后比较大小!
分析:这题没什么好说的,就是简单的进制转化问题,都转化为十进制然后比较一下,AC
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 20+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
typedef long long ll;
const double eps = 1e-9;
const double pi = acos(-1);
const ll mod = 1e9+7;
int main()
{
int n,k;
scanf("%d %d",&n,&k);
ll ans=0;
for(int i=0;i<n;i++)
{
int a;
scanf("%d",&a);
ans=ans*k+a;
}
scanf("%d %d",&n,&k);
ll ank=0;
for(int i=0;i<n;i++)
{
int a;
scanf("%d",&a);
ank=ank*k+a;
}
if(ans==ank)puts("=");
else if(ans>ank)puts(">");
else puts("<");
return 0;
}
B. Approximating a Constant Range
题意:给你一个数组,让你找出一种区间,这区间的最小值和最大值相差最大为1,求这类区间中的长度最大值。
题意:这题不太会,而且看别人的题解,也给出了好多方法,我学会了其中比较简单的一种——RMQ算法
先使用RMQ算法预处理出任意区间的最大值与最小值,然后这里的一个小技巧非常巧妙(暴搜会TLE)。有点类似贪心,选择两个指针一大一小,尽可能让后一个指针往后,直到不能往后再将前一个指针往后移,直到后一个指针越出边界。这样可以把n2的复杂度降到n,非常厉害!
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 100000+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
typedef long long ll;
const double eps = 1e-9;
const double pi = acos(-1);
const ll mod = 1e9+7;
int num[maxn];
int maxnum[maxn][21];
int minnum[maxn][21];
void init(int n)
{
clr(maxnum,0);
clr(minnum,0x3f3f3f3f);
for(int i=1;i<=n;i++)
maxnum[i][0]=minnum[i][0]=num[i];
for(int j=1;j<=20;j++)
for(int i=1;i<=n&&i+(1<<j)-1<=n;i++)
{
maxnum[i][j]=max(maxnum[i][j-1],maxnum[i+(1<<j-1)][j-1]);
minnum[i][j]=min(minnum[i][j-1],minnum[i+(1<<j-1)][j-1]);
}
}
int minrange(int l,int r)
{
int k=log(r-l+1)/log(2);
return min(minnum[l][k],minnum[r-(1<<k)+1][k]);
}
int maxrange(int l,int r)
{
int k=log(r-l+1)/log(2);
return max(maxnum[l][k],maxnum[r-(1<<k)+1][k]);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",num+i);
init(n);
int ans=0,p=1;
for(int i=1;i<=n;i++)
{
while(p<i&&maxrange(p,i)-minrange(p,i)>1)
p++;
ans=max(ans,i-p+1);
}
printf("%d\n",ans);
return 0;
}
C - The Two Routes
题意:给你一个完全图(边权都为1),分别将所有边标记为0和1,考察从结点1到结点n的路径。找出只经过0标记的边的路径和只经过1标记的边的路径,两种路径在1到n之间结点不能同时重合,问最后再结点n相遇的最小花费。
分析:看起来这题挺麻烦的,(而且说实话我都不知道我上面题意写的是啥东西),但是这道题其实非常水。因为这是完全图,那么结点1与结点n一定也存在一条边,那么在两种方式中我一定有一种方式可以花费单位1完成路径,而且不会与后一条路径有任何重合的可能。那么我们先标记每条边(邻接矩阵),考察maze[1][n],如果是1那么走0,如果是0走1。因为边权都是1,那么边权相当于没有,这样的话连最短路都不是,直接一个BFS,这是得到的最短距离就是要的结果!
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 400+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
typedef long long ll;
const double eps = 1e-9;
const double pi = acos(-1);
const ll mod = 1e9+7;
int maze[maxn][maxn];
int visit[maxn];
int main()
{
int n,m;
scanf("%d %d",&n,&m);
clr(maze,0);
while(m--)
{
int u,v;
scanf("%d %d",&u,&v);
maze[u][v]=maze[v][u]=1;
}
int k=maze[1][n];
k=(k+1)%2;
clr(visit,0);
queue<int>q;
q.push(1);
visit[1]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==n)
{
printf("%d\n",visit[n]-1);
return 0;
}
for(int i=1;i<=n;i++)
if(i!=u&&maze[u][i]==k&&visit[i]==0)
{
visit[i]=visit[u]+1;
q.push(i);
}
}
puts("-1");
return 0;
}