暑期集训1期11&&暑期集训一期12阶段性测验

暑期集训1期11

1.树状数组模板

2.线段树模板

暑期集训一期12阶段性测验

T1棒棒糖之王(^)前面讲过

T2烤乐滋埋雷(模拟)

在这里插入图片描述
用一个数组存储每一列是不是有炸弹,再用一个数组表示每一行有没有,最后一重循环判断即可

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int res=0;char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
    return res;
}
int n,m,k;
map<int,int>lie,hang;
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=k;i++)
    {
        int x,y;x=read();y=read();
        lie[y]++;hang[x]++;//两个标记
    }
    int tot1=0,tot2=0;
    for(int i=1;i<=n;i++)if(!hang[i])tot1++;
    for(int i=1;i<=m;i++)if(!lie[i])tot2++;
    cout<<tot1<<' '<<tot2;
    return 0;
}

T3阿卡翻硬币

在桌面上有一排漂亮的硬币,共N枚,每一枚硬币均为正面朝上(这很重要)。阿卡现在要把所 有的硬币翻转成反面朝上,规则是每次可翻转任意N-1枚硬币(正面向上的被翻转为反面向上,反之亦然)。求一个最短的操作序列(将每次翻转N-1枚硬币成 为一次操作)。当N比较大的时候阿卡遇到了困难,请号称程序员小能手的你棒棒忙

观察样例可以发现,翻转n-1,就是一个不翻。答案就是枚举1–n,表示不反转哪个,

#include<bits/stdc++.h>
using namespace std;
int n,a[150];
int main()
{
    cin>>n;
    cout<<n<<endl;
    for(int i=1;i<=n;i++)//翻转哪个
    {
       for(int j=1;j<=n;j++)
       if(i!=j)a[j]=!a[j];
       for(int j=1;j<=n;j++)cout<<a[j];
       cout<<endl;
    }
    return 0;
}


T4小飞侠的游园方案

题目花里胡哨的,不放了,其实就是01背包模板

#include<bits/stdc++.h>
using namespace std;
int n,m;
int dp[11000],f[110],t[110];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>f[i]>>t[i];
    for(int i=1;i<=n;i++)
    for(int j=m;j>=t[i];j--)//倒着来
    dp[j]=max(dp[j],dp[j-t[i]]+f[i]);
    cout<<dp[m];
    return 0;
}

T5 完全背包

完全背包模板…

#include<bits/stdc++.h>
using namespace std;
int n,m;
int dp[250],f[250],t[250];
int main()
{
    cin>>m>>n;
    for(int i=1;i<=n;i++)cin>>t[i]>>f[i];
    for(int i=1;i<=n;i++)
    for(int j=t[i];j<=m;j++)//顺序可以重复选
    dp[j]=max(dp[j],dp[j-t[i]]+f[i]);
    cout<<"max="<<dp[m];
    return 0;
}

T6瓦卡分水果在这里插入图片描述

选择贪心,将两种果子从大到小进行排序,然后一一匹配,看看谁的指针往后大,谁就往后,指针到了最后面,转换的第一个

#include<bits/stdc++.h>
using namespace std;
int a[150000],b[150000];
int n,m,k;
long long ans;
int read()
{
    int res=0;char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
    return res;
}
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++)b[i]=read();
    int atep=1,btep=1;
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+m,cmp);
    for(int i=1;i<=k;i++)
    {
        ans=a[atep]+b[btep];
        printf("%d\n",ans);
        if(a[atep]+b[btep+1]>=b[btep]+a[atep+1])//比比谁大
        {
            btep++;
            if(btep>m)btep=1,atep++;
        }
        else
        {
            atep++;
            if(atep>n)atep=1,btep++;
        }
    }
    return 0;
}


T7 最小花费

在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。
变异spfa,dis[i]表示要交税的比率,spfa的转移时是比率相乘,建边的时候要建双向边,先算好每一条边的比率

#include<bits/stdc++.h>
#define maxn 950000
using namespace std;
long long head[maxn],n,m,tot;
double dis[maxn];
struct ndoe{
    int u;
    int to;
    double z;   
}edge[maxn<<1];
void add(int x,int y,double z)
{
    ++tot;
    edge[tot].u=head[x];
    edge[tot].to=y;
    edge[tot].z=z;
    head[x]=tot;
}
queue<int>q;
int vis[maxn];
void spfa(int x)
{
    dis[x]=1;
    vis[x]=1;
    q.push(x);
    while(!q.empty())
    {
        int k=q.front();q.pop();vis[k]=0;
         
        for(int i=head[k];i;i=edge[i].u)
        {   
            int t=edge[i].to;
            if(dis[t]<dis[k]*edge[i].z)//比率相乘
            {
                dis[t]=dis[k]*edge[i].z;
                if(!vis[t])
                {
                    vis[t]=1;
                    q.push(t);
                }           
            }
         
        }
    }
}
int main()
{
    cin>>n>>m;
 
    for(int i=1;i<=m;i++)
    {
        int x,y,z;cin>>x>>y>>z;
        add(x,y,(100.00-z)*0.01);
        add(y,x,(100.00-z)*0.01);//注意双向建边
    }   int s,e;cin>>s>>e;
    spfa(s);
    double q=100*1.0000/dis[e]*1.0;
    printf("%.8f",q);
    return 0;
}


T8阿卡的萝卜加强版

在这里插入图片描述
线段树的模板加上一个函数,pushup,在这个函数中用一个数组res保存一段内的最长连续字段和,看看这一段是从左儿子的值+自己大,右儿子+自己大,左+右+自己大

#include<bits/stdc++.h>
using namespace std;
#define lson rt*2
#define rson rt*2+1
#define N  1500000+100
int n,m,lmx[N],rmx[N],res[N],sum[N];
 
void pushup(int rt) 
{
    sum[rt]=sum[lson]+sum[rson];//更新父节点
    lmx[rt]=max(lmx[lson],sum[lson]+lmx[rson]);//左边
    rmx[rt]=max(rmx[rson],sum[rson]+rmx[lson]);//右边
    res[rt]=max(rmx[lson]+lmx[rson],max(res[lson],res[rson]));//整段
}
void build(int rt,int l,int r) //建树
{
    if(l==r) 
    {
        scanf("%d",&sum[rt]);
        lmx[rt]=rmx[rt]=res[rt]=sum[rt];//最大更新为自己先
        return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);//递归左儿子
    build(rson,mid+1,r);//递归右儿子
    pushup(rt);
}
void Update(int x,int rt,int l,int r,int val) 
{//单点修改 :改动的编号 目前节点 左端点 右端点 改的值
    if(l==r) 
    {
        int p=sum[rt]+val;
        sum[rt]=lmx[rt]=rmx[rt]=res[rt]=p;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)Update(x,lson,l,mid,val);
    else Update(x,rson,mid+1,r,val);
    pushup(rt);
}
int main() 
{
    scanf("%d",&n);
    build(1,1,n);
    scanf("%d",&m);
    while(m--)
    {
        string c;scanf("%s",&c[0]);
        if(c[0]=='Q')printf("%d\n",res[1]);
        else
        {
          int x;scanf("%d",&x);
          if(c[0]=='J')Update(x,1,1,n,1);
          else Update(x,1,1,n,-1);      
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值