其他分享
首页 > 其他分享> > 周练3,题解

周练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