暑期集训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瓦卡分水果![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/95c02051000f9a33cbff00e69cee7004.png)
选择贪心,将两种果子从大到小进行排序,然后一一匹配,看看谁的指针往后大,谁就往后,指针到了最后面,转换的第一个
#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;
}