2022.3.7
蓝书
AcWing 100. IncDec序列
思路:一开始想的是每个数都减去一个数,以为是平均值,后面想到差分就让每个数减去它前面一个构造了差分数组,因为我们最终是要让序列的每一个数都一样,所以我们让b[1]=a[1],让b[2-n]变成0,预处理出2-n的正数和z和负数和f,一部分的操作次数就是现在z和f消去一部分即min(z,f),剩下一部分我们考虑与a[1]相消去,于是答案为min(z,f)+abs(z-f),这里有abs(z-f)+1种排列方式,+1是因为z和f可能相等,那么a[1]本身就是一种排列方式了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10,INF=1e8;
ll a[N],b[N],n;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n;i++)
scanf("%lld",&a[i]);
b[1] = a[1];
ll z = 0, f = 0,ans=0;
for (int i = 2; i <= n;i++)
{
b[i] = a[i] - a[i - 1];
if(b[i]>0)
z += b[i];
else
f -= b[i];
}
ans += min(z, f)+abs(z-f);
printf("%lld\n%lld", ans, abs(f - z) + 1);
return 0;
}
AcWing 101. 最高的牛
思路:如果两头牛要相互看的见的话它们之间的牛的身高必须都小于他们,于是我们对每次输入的牛让它们之间的牛身高都-1,利用差分数组记录一下每对牛之间的相对关系,最后转化成前缀和再加上最高的牛的身高。
一开始判重用的是int数组结果超内存了,改用map就过了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int N=1e4+10,INF=1e8;
map<pair<int, int>,int> mp;
int ans[N];
int main()
{
int n, p, h, m;
scanf("%d%d%d%d", &n, &p, &h, &m);
for (int i = 1; i <= m;i++)
{
int a, b;
scanf("%d%d", &a, &b);
if(a>b)
swap(a, b);
if(mp[{a,b}])
continue;
mp[{a,b}] = 1;
ans[a + 1]--;
ans[b]++;
}
for (int i = 1; i <= n;i++)
{
ans[i] +=ans[i-1];
printf("%d\n", ans[i]+h);
}
return 0;
}
AcWing 102. 最佳牛围栏
思路:要求平均值*1000,应该用浮点数二分,为了简便计算,对于每个数我们都先减去二分的平均值,这下问题可以转化成在一个序列中求长度不超过L的非负子段和。因为每块地最多也就只有2000头牛,假设每块地都有2000头牛的话,那么二分答案的最大值也就是2000,因此可以缩小二分的范围,在二分的过程中,我们不必枚举每次的最小值,只需要在i增长的过程中记录下当前的最小值就可以,同时不断更新答案:b[i]-mmin。
一开始减平均值的时候想错了,没在二分的时候减。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10,INF=1e8;
int n, m;
double a[N], b[N];
int check(double mid)
{
double mmin = INF, mmax = -INF;
for (int i = 1; i <= n;i++)
b[i] = b[i - 1] + a[i] - mid;
for (int i = m; i <= n;i++)
{
mmin = min(mmin, b[i - m]);
mmax = max(mmax, b[i] - mmin);
}
return mmax >= 0;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n;i++)
{
scanf("%lf", &a[i]);
}
double l = 0, r = 2000;
while(r-l>1e-5)
{
double mid = (l + r) / 2;
if(check(mid))
l = mid;
else
r = mid;
}
printf("%d", int(r * 1000));
return 0;
}
AcWing 174. 推箱子
写着写着人突然头晕,晚点补
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N=20+10,INF=1e8;
int n, m, t;
struct node
{
int x, y, dir;
};
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
PII dist[N][N][4];
node prebox[N][N][4];
int preman[N][N];
bool visman[N][N], visbox[N][N][4];
vector<int> road[N][N][4];
char mp[N][N];
const char op[5] = "nswe";
int check(int x,int y)
{
if(x>=0&&x<n&&y>=0&&y<m&&mp[x][y]!='#')
return 1;
return 0;
}
int bfs2(PII start,PII end,PII box,vector<int>&seq)
{
memset(visman, 0, sizeof visman);
memset(preman, -1, sizeof preman);
visman[start.first][start.second] = 1;
visman[box.first][box.second] = 1;
queue<PII> que;
que.push(start);
while(que.size())
{
auto t = que.front();
que.pop();
if(t==end)
{
seq.clear();
while(preman[t.first][t.second]!=-1)
{
int dir = preman[t.first][t.second];
seq.push_back(dir);
t.first += dx[dir], t.second += dy[dir];
}
return seq.size();
}
for (int i = 0; i < 4;i++)
{
int a = t.first - dx[i], b = t.second - dy[i];
if(check(a,b)&&!visman[a][b])
{
visman[a][b] = 1;
preman[a][b] = i;
que.push({a, b});
}
}
}
return -1;
}
bool bfs1(PII start,PII box,node &ed)
{
memset(visbox, false, sizeof visbox);
queue<node> que;
for (int i = 0; i < 4;i++)
{
int bx = box.first - dx[i];
int by = box.second - dy[i];
int mx = box.first + dx[i];
int my = box.second + dy[i];
if(check(mx,my)&&check(bx,by))
{
vector<int> seq;
int len = bfs2(start, {mx, my}, box, seq);
if(len==-1)
continue;
que.push({bx, by, i});
visbox[bx][by][i] = 1;
road[bx][by][i] = seq;
dist[bx][by][i] = {1, len};
prebox[bx][by][i] = {box.first, box.second, -1};
}
}
PII mmax = {1e9, 1e9};
while(que.size())
{
auto t = que.front();
que.pop();
PII &v = dist[t.x][t.y][t.dir];
if(mp[t.x][t.y]=='T'&&v<mmax)
{
ed = t;
mmax = v;
}
for (int i = 0; i < 4;i++)
{
int bx = t.x - dx[i];
int by = t.y - dy[i];
int mx = t.x + dx[i];
int my = t.y + dy[i];
if(check(mx,my)&&check(bx,by))
{
vector<int> seq;
int len = bfs2({t.x+dx[t.dir],t.y+dy[t.dir]},{mx,my},{t.x,t.y},seq);
if(len==-1)
continue;
PII distance = {v.first + 1, v.second + len};
if(!visbox[bx][by][i])
{
que.push({bx, by, i});
visbox[bx][by][i] = 1;
road[bx][by][i] = seq;
dist[bx][by][i] = distance;
prebox[bx][by][i] = t;
}
else if(dist[bx][by][i]>distance)
{
dist[bx][by][i] = distance;
road[bx][by][i] = seq;
prebox[bx][by][i] = t;
}
}
}
}
//printf("%d\n", mmax.first);
return mmax.first!=1e9;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
PII start, box;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
{
cin >> mp[i][j];
if (mp[i][j] == 'S') start = {i,j};
else if (mp[i][j] == 'B') box = {i,j};
}
node end;
string ans;
printf("Maze #%d\n", ++t);
if(bfs1(start, box, end))
{
while (end.dir!=-1)
{
ans += op[end.dir] - 32;
for (int i = 0; i < road[end.x][end.y][end.dir].size(); i ++ )
ans += op[road[end.x][end.y][end.dir][i]];
end = prebox[end.x][end.y][end.dir];
}
reverse(ans.begin(), ans.end());
cout << ans << endl<< endl;
}
else
{
printf("Impossible.\n\n");
}
}
return 0;
}