周练3,题解
作者:互联网
非男非女
思路 :输入处理时先把女生标记为-1,那么女生和男生配对和就是0 ,那么利用前缀和就
好找到一个连续的和为0 的长区间了
#include<iostream>
using namespace std;
const int N = 100010;
int n;
int s[N];
int main() {
int max = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%d", &s[i]);
if (s[i] == 0) s[i] = -1;//处理一下然后搞前缀和
s[i] += s[i - 1] ;
}
//双指针找最长的区间使得,s[i] == s[j] ,那么i——j之间的数和为0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
if (s[i] == s[j]) {
if (i - j > max) {
max = i - j;
}
break;
}
}
}
cout << max;
return 0;
}
下面展示一些 内联代码片
。
激光炸弹
二维前缀和,但是还是要注意一些,目标在点上面不是方块
![红点标记的是目标,红色正方形里面!里面!里面!是包砸的范围,红点目标在红色正方形里面就可以被炸](https://www.icode9.com/i/ll/?i=20210411115844608.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMwMzI4MTQ1,size_16,color_FFFFFF,t_70)
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int N =5010;
int s[N][N];
int main(){
int n,m;
int cnt,R;
cin>>cnt>>R;
R=min(5002,R);//目标范围不大的
n=m=R;//n和m表示最大边界,这里要先定义,否则后面可能会报错
while(cnt--){
int x,y,w;
cin>>x>>y>>w;
x++,y++;//前缀和(1,1)为开头的,所以++好记录
n=max(n,x),m=max(m,y);
s[x][y]+=w;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
s[i][j]+=s[i-1][j]+s[i][j-1] - s[i-1][j-1];
}
int res=0;
for(int i=R;i<=n;i++)
for(int j=R;j<=m;j++){
res=max(res,s[i][j]-s[i-R][j]-s[i][j-R] +s[i-R][j-R]);
}
cout<<res<<endl;
}
快递员送件
这题用堆优化版Dijkstra,大概率用SPFA也是可以过的。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
int n, m;
int h[N], w[N], e[N], ne[N], idx;//邻接表来存
int dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;//这里大家可以查一查资料
heap.push({0, 1});
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b,a,c);
}
int ans=0;
dijkstra();
for(int i=1;i<=n;i++) ans+=(dist[i]*2);//改了一下这里,其他都是模板
cout<<ans;
return 0;
}
小明与区间
就是星期二讲的线段树,不过把找最大值盖臣找最小值,把编号1~N 改成了0~N-1;
其他一模一样的,所以我直接拿那天晚上学长发的代码改了一点就过了,也让大家再一次复习一下
不过ck学长的代码在c++,c++11会被卡时间,要在Visual C++里可以过
所以放两个代码,一个是ck学长的模板改的,另一个是用了快读的
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int maxn[N << 2], n, m;
inline void build(int rt, int l, int r) {
if (l == r) {
scanf("%d", &maxn[rt]);
return ;
}
int mid = (l + r) / 2;
build(rt * 2, l, mid);
build(rt * 2 + 1, mid + 1, r);
maxn[rt] = min(maxn[rt * 2], maxn[rt * 2 + 1]);
}
//[l, r]
inline int query(int rt, int l, int r, int L, int R) {
if (l >= L && r <= R) {
return maxn[rt];
}
int mid = (l + r) / 2, ans =0x3f3f3f3f;
if (L <= mid) {
ans = min(query(rt * 2, l, mid, L, R), ans);
}
if (R > mid) {
ans = min(query(rt * 2 + 1, mid + 1, r, L, R), ans);
}
return ans;
}
inline void update(int rt, int l, int r, int x, int v) {
if (l == r) {
maxn[rt] = v;
return ;
}
int mid = (l + r) / 2;
// [l, mid], [mid + 1, r]
if (x <= mid) {
update(rt * 2, l, mid, x, v);
}
else {
update(rt * 2 + 1, mid + 1, r, x, v);
}
maxn[rt] =min(maxn[rt * 2], maxn[rt * 2 + 1]);
}
int main() {
scanf("%d", &n); build(1, 1, n);
scanf("%d", &m);
int op;
for (int i = 1, a, b; i <= m; i++) {
scanf("%d %d %d", &op, &a, &b);
if (op == 0 ) printf("%d\n", query(1, 1, n, a+1, b+1));
else update(1, 1, n, a+1, b);
}
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int tr[4000010];
int a[1000010],n,q;
int ans;
inline void build(int l,int r,int o)
{
if(l==r) tr[o]=a[l];
else
{
int mid=l+r>>1;
build(l,mid,o<<1);
build(mid+1,r,o<<1|1);
tr[o]=min(tr[o<<1],tr[o<<1|1]);
}
}
inline void upd(int l,int r,int o,int pos,int x)
{
if(l==r) tr[o]=x;
else
{
int mid=l+r>>1;
if(mid>=pos) upd(l,mid,o<<1,pos,x);
else upd(mid+1,r,o<<1|1,pos,x);
tr[o]=min(tr[o<<1],tr[o<<1|1]);
}
}
inline void query(int l,int r,int o,int L,int R)
{
if(L>R) return;
if(l==L&&r==R) ans=min(ans,tr[o]);
else
{
int mid=l+r>>1;
query(l,mid,o<<1,L,min(mid,R));
query(mid+1,r,o<<1|1,max(mid+1,L),R);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
a[i]=read();
build(0,n-1,1);
scanf("%d",&q);
int op,l,r;
while(q--)
{
op=read(),l=read(),r=read();
if(op==1) upd(0,n-1,1,l,r);
else
{
ans=1e9;
query(0,n-1,1,l,r);
printf("%d\n",ans);
}
}
}
林克解救呀哈哈:
```cpp
#include<iostream>
#include<cstring>
using namespace std;
char map[101][101];//储存地图
int a[101][101],ans=0,m,n;
void res(int u,int v,int i,int j)//u,v是起点坐标,i,j为终点坐标
{
int t=a[u][v];//记录
if(u==i&&v==j) ans=t;//如果到达终点,更新ans
t++;//走一步
if(v<m-1&&map[u][v+1]!='#'&&a[u][v+1]>t)//不超界限&&不是怪物&&更优
{
a[u][v+1]=t;//更新
res(u,v+1,i,j);//继续遍历下一方案
}
if(u>0&&map[u-1][v]!='#'&&a[u-1][v]>t)//同上
{
a[u-1][v]=t;//同上
res(u-1,v,i,j);//同上
}
if(v>0&&map[u][v-1]!='#'&&a[u][v-1]>t)
{
a[u][v-1]=t;
res(u,v-1,i,j);
}
if(u<n-1&&map[u+1][v]!='#'&&a[u+1][v]>t)
{
a[u+1][v]=t;
res(u+1,v,i,j);
}
}
int main()
{
int startx,starty,endx,endy;//前两者是林克坐标,后两者是呀哈哈的坐标
while(cin>>n>>m&&m!=0&&n!=0)//输入
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>map[i][j];//尽量别用scanf,容易出错
if(map[i][j]=='@')//标记
{
startx=i;
starty=j;
}
if(map[i][j]=='*')//标记
{
endx=i;
endy=j;
}
}
}
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++)
a[i][j] = 9999; //把所有路都置为一个很大的值
a[startx][starty]=0;//一开始到达起点不要步数
res(startx,starty,endx,endy);//调用
if(ans!=0) cout<<ans<<endl;
else cout<<-1<<endl;
ans=0;
}
}
签到题:
蛇形矩阵,会设置方向就好
```c
```cpp
```csharp
```cpp
#include <iostream>
using namespace std;
const int N=110;
int f[N][N];
int n;
int main()
{
cin >> n ;
int dx[]={-1, 0, 1, 0}, dy[]={0, 1, 0, -1};
int d = 2,x = 0,y = n-1;
int a,b;
for(int i = 1; i <=n*n; i++)
{
f[x][y] = i;
a = x + dx[d];
b = y + dy[d];
if(a < 0 || a>=n || b<0 || b>=n ||f[a][b] )
{
d = (d+1)%4;
a = x + dx[d];
b = y + dy[d];
}
x = a;
y = b;
}
for(int i = 0; i < n; i++ )
{
for(int j = 0; j < n; j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
}
蘑菇与花朵:原题红与黑,深搜老模板了
```cpp
#include <iostream>
using namespace std;
int m,n;
const int N = 30;
char f[N][N];
int dx[] = {-1 , 0 , 1, 0}, dy[] = {0 , 1 , 0, -1};
int dfs(int x, int y)
{
f[x][y] = '#';
int res = 1;
for(int i = 0; i < 4; i++ )
{
int a = x + dx[i];
int b = y + dy[i];
if(a >= 0 && a < n && b >= 0 && b< m && f[a][b] =='.') res += dfs(a,b);
}
return res;
}
int main()
{
while(cin >> m >> n, m || n )
{
int a,b;
for(int i = 0; i< n; i++ )
{
for(int j = 0; j < m ; j++)
{
cin >> f[i][j];
if(f[i][j] == '@')
{
a = i;
b = j;
}
}
}
cout << dfs(a,b) << endl;
}
return 0;
}
祝你生日快乐:
由于要保证最后所有的蛋糕面积相同,所以必须按照比例切。
目前边长为 x 和 y ,需要 n 块蛋糕。如果横着切,枚举上面一块的蛋糕数 i ,那么下面一块就需要 n−i 块,也就是说上面的边长是 xi/n,y ,下面的边长为 x(n−i)n,y(保持面积相等)。竖着切同理。
#include<cstdio>
#include<algorithm>
#include <iostream>
using namespace std;
const int maxn=10000;
int x,y,n;
double Dfs(double x,double y,int n)
{
if (n==1) return max(x,y)/min(x,y);double ans=1e100;
for (int i=1;i<n;i++) ans=min(ans,max(Dfs(x*i/n,y,i),Dfs(x*(n-i)/n,y,n-i)));
for (int i=1;i<n;i++) ans=min(ans,max(Dfs(x,y*i/n,i),Dfs(x,y*(n-i)/n,n-i)));
return ans;
}
int main()
{
scanf("%d%d%d",&x,&y,&n);
printf("%.6lf\n",Dfs(x,y,n));
}
标签:rt,int,题解,mid,&&,ans,周练,include 来源: https://blog.csdn.net/qq_30328145/article/details/115561157