A
小学数学题
#include<bits/stdc++.h>
using namespace std;
long long f[102];
void init(){
f[1]=1;
for(int i=2;i<=101;i++){
f[i]=f[i-1]+(i-1)*4;
}
}
int main(){
init();
int n;
cin>>n;cout<<f[n]<<endl;
return 0;
}
B
题意:
现在有一个数组,你可以选择若干个 a i a_i ai将它们变成 − a i − 1 -a_i-1 −ai−1,使得他们的乘积最大。输出一种可行方案
思路:
先把所有的非负数变为 − a i − 1 -a_i-1 −ai−1,然后统计现在负数的个数,若为偶数,则不操作,否则选择最小的那个负数变为 − a i − 1 -a_i-1 −ai−1。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
int a[N];
int main(){
int n;
int neg=0;
cin>>n;for(int i=1;i<=n;i++){
cin>>a[i];if(a[i]>=0) a[i]=-a[i]-1;
}
for(int i=1;i<=n;i++){
if(a[i]<0) neg++;
}
if(neg&1){
int minn=0;
for(int i=1;i<=n;i++) minn=min(minn,a[i]);
for(int i=1;i<=n;i++){
if(a[i]==minn){
a[i]=-a[i]-1;break;
}
}
}
for(int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<endl;
return 0;
}
C
题意:
一个长度为 n n n的双端队列,你执行无数次下列操作:取出队列顶端的前两个数 a , b a,b a,b,大的放在队列顶端,小的放到队列尾部,现在给你 q q q次查询,查询每次操作的 a , b a,b a,b。
思路:
手动模拟一遍一会发现,前 n n n次是不确定的,经过 n n n次之后变成了每 n − 1 n-1 n−1次一个循环,因此只需先记录 2 ∗ n − 1 2*n-1 2∗n−1次,然后对于查询直接查询即可,复杂度 O ( n ∗ l o g ( n ) ) O(n*log(n)) O(n∗log(n))
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long n,m,x;
scanf("%I64d%I64d",&n,&m);
map<long long ,pair<long long,long long> > mmp1,mmp2;
deque<long long> q;
for(int i=1;i<=n;i++){
scanf("%I64d",&x);q.push_back(x);
}
for(int j=1;j<=n;j++){
int A=q.front();q.pop_front();
int B=q.front();q.pop_front();
//cout<<j<<' '<<A<<' '<<B<<endl;
mmp1[j]={A,B};
if(A>B){
q.push_front(A);
q.push_back(B);
}
else{
q.push_front(B);
q.push_back(A);
}
}
for(int j=1;j<=n-1;j++){
int A=q.front();q.pop_front();
int B=q.front();q.pop_front();
//cout<<j<<' '<<A<<' '<<B<<endl;
mmp2[j]={A,B};
if(A>B){
q.push_front(A);
q.push_back(B);
}
else{
q.push_front(B);
q.push_back(A);
}
}
long long Q;
while(m--){
scanf("%I64d",&Q);
if(Q<=n){
printf("%I64d %I64d\n",mmp1[Q].first,mmp1[Q].second);
}
else{
Q-=n;
if(Q%(n-1)==0) printf("%I64d %I64d\n",mmp2[n-1].first,mmp2[n-1].second);
else printf("%I64d %I64d\n",mmp2[Q%(n-1)].first,mmp2[Q%(n-1)].second);
}
}
return 0;
}
D
题意:
一个 n ∗ m n*m n∗m的网状图,你要访问每个格点,你的初始格点在 ( 1 , 1 ) (1,1) (1,1),现在你可以从 ( x , y ) (x,y) (x,y)到达 ( x + d x , y + d y ) (x+dx,y+dy) (x+dx,y+dy),你要构造一个遍历顺序使得每次的 d x , d y dx,dy dx,dy都不相同并且能遍历完所有的点。
思路
( 1 , 1 ) − > ( n , m ) − > ( n , m − 1 ) − > ( 1 , 2 ) − > . . . . . . − > ( n , 1 ) − > ( 2 , 1 ) . . . . . (1,1)->(n,m)->(n,m-1)->(1,2)->......->(n,1)->(2,1)..... (1,1)−>(n,m)−>(n,m−1)−>(1,2)−>......−>(n,1)−>(2,1).....
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<=n/2;i++){
for(int j=1;j<=m;j++){
printf("%d %d\n",i,j);
printf("%d %d\n",n+1-i,m+1-j);
//<<n+1-i<<' '<<m+1-j<<endl;
}
}
if(n&1){
if(m&1){
for(int i=1;i<=m/2;i++){
printf("%d %d\n",n/2+1,i);
printf("%d %d\n",n/2+1,m+1-i);
}
printf("%d %d\n",n/2+1,m/2+1);
//cout<<n/2+1<<' '<<m/2+1<<endl;
}
else{
for(int i=1;i<=m/2;i++){
printf("%d %d\n",n/2+1,i);
printf("%d %d\n",n/2+1,m+1-i);
//cout<<n/2+1<<' '<<m+1-i<<endl;
}
}
}
return 0;
}
E
题意:
有 n n n盘菜, m m m个学生,每盘菜的价格为 a i a_i ai,每个学生带的钱为 b i b_i bi,每个学生会买他所能买的最贵的菜,现在有 q q q次修改,每次你可以把 a i a_i ai变为 x x x,或者把 b i b_i bi变为 x x x,对于每次修改,计算剩下的最贵的菜的价格,如果没有,则输出 − 1 -1 −1。
思路:
对于每个 a i a_i ai,我们将区间 [ 1 , a i ] [1,a_i] [1,ai]加 1 1 1,对于每个 b i b_i bi,我们将区间 [ 1 , b i ] [1,b_i] [1,bi]减 1 1 1,每次查询统计最大的不为 0 0 0的数,如果没有输出 − 1 -1 −1,线段树即可完成操作,复杂度 O ( n ∗ l o g ( n ) ) O(n*log(n)) O(n∗log(n))
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+100;
int tag[N<<1],maxx[N<<1];
int a[N],b[N];
void pushdown(int rt,int l,int r){
if(tag[rt]){
tag[rt<<1]+=tag[rt];
tag[rt<<1|1]+=tag[rt];
maxx[rt<<1]+=tag[rt];
maxx[rt<<1|1]+=tag[rt];
tag[rt]=0;
}
}
void update(int rt,int nl,int nr,int l,int r,int x){
if(nl<=l&&r<=nr){
maxx[rt]+=x;
tag[rt]+=x;
return ;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(nl<=mid) update(rt<<1,nl,nr,l,mid,x);
if(nr>mid) update(rt<<1|1,nl,nr,mid+1,r,x);
maxx[rt]=max(maxx[rt<<1|1],maxx[rt<<1]);
}
int query(int rt,int l,int r){
if(l==r){
return l;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(maxx[rt<<1|1]>0){
return query(rt<<1|1,mid+1,r);
}
return query(rt<<1,l,mid);
}
int main(){
int n,m,q;
scanf("%d %d",&n,&m);
memset(maxx,0,sizeof(maxx));
memset(tag,0,sizeof(tag));
for(int i=1;i<=n;i++) scanf("%d",&a[i]),update(1,1,a[i],1,2000002,1);
for(int i=1;i<=m;i++) scanf("%d",&b[i]),update(1,1,b[i],1,2000002,-1);
//cout<<query(1,1,2000002)<<endl;
scanf("%d",&q);
while(q--){
int op,id,num;
scanf("%d %d %d",&op,&id,&num);
if(op==1){
update(1,1,a[id],1,2000002,-1);
a[id]=num;
update(1,1,a[id],1,2000002,1);
}
else{
update(1,1,b[id],1,2000002,1);
b[id]=num;
update(1,1,b[id],1,2000002,-1);
}
int ok=query(1,1,2000002);
if(maxx[1]<=0) puts("-1");
else printf("%d\n",ok);
}
return 0;
}