A.链接:点击打开链接
题意:在一个N*M的棋盘上,'.'为可放棋的点,'-'为不放棋的点,有'B'和'W'两种棋,要求这两种棋不能相邻,输出满足条件的棋盘
代码:
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main(){
int n,m,i,j,k;
char s[105][105];
while(scanf("%d%d",&n,&m)!=EOF){
memset(s,0,sizeof(s)); //就是一个国际象棋的棋盘...
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf(" %c",&s[i][j]);
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(s[i][j]=='.'){
if(i%2){
if(j%2)
printf("B");
else
printf("W");
}
else{
if(j%2)
printf("W");
else
printf("B");
}
}
else
printf("%c",s[i][j]);
}
printf("\n");
}
}
return 0;
}</span>
B.链接:点击打开链接
题意:有n种药品,m种反应,反应可以翻倍,例如1,2反应,2,3反应,则当1在试管中时,将2放入试管种威力乘2,再将3放入试管中,威力则再乘2,初始威力为1,输出最后的威力
代码:
<span style="font-size:18px;">#include <queue>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int par[105],r[105];
int find(int x){
if(x==par[x])
return x;
return par[x]=find(par[x]);
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y)
return;
if(r[x]<r[y])
par[x]=y;
else{
par[y]=x;
if(r[x]==r[y])
r[x]++;
}
}
bool same(int x,int y){
return find(x)==find(y);
} //并查集模板
int main(){
int i,j,n,m,a,b,ans,sum;
while(scanf("%d%d",&n,&m)!=EOF){
ans=0;
for(i=0;i<=n;i++){
par[i]=i;
r[i]=0;
}
while(m--){
scanf("%d%d",&a,&b);
unite(a,b);
}
sum=0;
for(i=1;i<=n;i++){
if(par[i]==i){
sum++;
} //注意求的其实是联通数的个数
}
printf("%I64d\n",(long long)pow(2,n-sum));
}
return 0;
}</span>
C.链接:点击打开链接
题意:有一个图,每个顶点有一个权值,每一条边有一个权值,求边的权值除以边两个顶点的权值的和的最大值
代码:
<span style="font-size:18px;">#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int num[505];
int main(){
int n,m,i,j,a,b,c,p,q;
double s,ans;
while(scanf("%d%d",&n,&m)!=EOF){
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
ans=0;
while(m--){
scanf("%d%d%d",&a,&b,&c);
ans=max(ans,(num[a]+num[b])*1.0/c);
}
printf("%.15lf\n",ans);
}
return 0;
}</span>
D.链接:点击打开链接
题意:由题目给出的一段程序,随机给出数组a和数组b,根据下图公式输出数组c
代码:
<span style="font-size:18px;">#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
long long n,d,x;
long long a[500005],b[500005],c[500005];
long long getNextX(){
x=(x*37+10007)%1000000007;
return x;
}
long long initAB(){
long long i;
for(i=0;i<n;i=i+1)
a[i]=i+1;
for(i=0;i<n;i=i+1)
swap(a[i],a[getNextX()%(i+1)]);
for(i=0;i<n;i=i+1){
if(i<d)
b[i]=1;
else
b[i]=0;
}
for(i=0;i<n;i=i+1)
swap(b[i],b[getNextX()%(i + 1)]);
}
int main(){
long long i,j,ans;
while(scanf("%I64d%I64d%I64d",&n,&d,&x)!=EOF){
initAB();
vector<long long> v;
for(i=0;i<n;i++)
if(b[i])
v.push_back(i); //因为数组b只能是0或1,因此b中1的个数决定了算出c的复杂度
if(v.size()<(long long)sqrt(n)){ //当b中1的个数较少时,可以直接输出c
for(i=0;i<n;i++){
ans=0;
for(j=0;j<v.size()&&v[j]<=i;j++)
ans=max(ans,a[i-v[j]]);
printf("%I64d\n",ans);
}
}
else{
for(i=0;i<=n;i++)
c[i]=n+1;
for(i=0;i<n;i++)
c[a[i]]=i;
for(i=0;i<n;i++){
for(j=n;j>0;j--){ //记录每个值的位置,判断最近的数组b为1的位置
if(c[j]<=i&&b[i-c[j]]){
printf("%I64d\n",j);
break;
}
}
if(j==0)
puts("0");
}
}
}
return 0;
}</span>
E.链接:点击打开链接
题意:给出n个数,初始为1~n,有m个操作,一种是将区间[l,r]内的值改为x,同时改点会累加一个|x-y|的值,第二种询问[l,r]区间内产生的累加值的和
代码:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
const long long SIZE=100005; //用两个标记,一个是懒惰标记,另一个是判断该节点表示的
long long cnt[SIZE<<2],add[SIZE<<2],sum[SIZE<<2];
void pushup(int rt){ //区间是否是同一个值
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
if(cnt[rt<<1]&&cnt[rt<<1]==cnt[rt<<1|1])
cnt[rt]=cnt[rt<<1];
else
cnt[rt]=0;
}
void pushdown(long long rt,long long m){
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*(m-(m>>1));
sum[rt<<1|1]+=add[rt]*(m>>1);
cnt[rt<<1]=cnt[rt<<1|1]=cnt[rt];
add[rt]=0;
}
}
void build(long long l,long long r,long long rt){
long long m;
add[rt]=sum[rt]=0;
if(l==r){
cnt[rt]=l;
return ;
}
m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(long long L,long long R,long long c,long long l,long long r,long long rt){
long long m;
if(L<=l&&r<=R&&cnt[rt]){ //同一个值才更新
add[rt]+=abs(cnt[rt]-c);
sum[rt]+=abs(cnt[rt]-c)*(r-l+1); //不是同一个值就无法直接懒惰标记更新
cnt[rt]=c;
return;
}
pushdown(rt,r-l+1);
m=(l+r)>>1;
if(L<=m)
update(L,R,c,l,m,rt<<1);
if(R>m)
update(L,R,c,m+1,r,rt<<1|1);
pushup(rt);
}
long long query(long long L,long long R,long long l,long long r,long long rt){
long long m,ans;
if(L<=l&&r<=R)
return sum[rt];
pushdown(rt,r-l+1);
ans=0;
m=(l+r)>>1;
if(L<=m)
ans+=query(L,R,l,m,rt<<1);
if(R>m)
ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
} //线段树区间询问
int main(){
long long n,m,i,j,a,b,c,ch,sign;
while(scanf("%I64d%I64d",&n,&m)!=EOF){
build(1,n,1);
while(m--){
scanf("%I64d",&ch);
if(ch==2){
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",query(a,b,1,n,1));
}
else{
scanf("%I64d%I64d%I64d",&a,&b,&c);
update(a,b,c,1,n,1);
}
}
}
return 0;
}