A : A Variety of Operations
解题思路 :
~略
AC代码 :
#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py puts("Yes")
#define pn puts("No")
#define pcn putchar('\n')
#define pcs putchar(' ')
#define pc(a) putchar(a)
#define pb(a) push_back(a)
inline void intxt( ){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
}
inline int read( ){
int f = 1,x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
return x;
}
const int maxn=5e5+5;
ll c,d;
int main(){
txt;
CAS{
cin>>c>>d;
if(c==d && c==0){
cout<<0<<endl;
continue;
}
if( abs(c-d)%2!=0 ){
cout<<-1<<endl;
continue;
}
if(c==d){
cout<<1<<endl;
}else{
cout<<2<<endl;
}
}
return 0;
}
B : Take Your Places!
题意:
给长度为n的a数组 , 问最少可以进行多少次交换相邻元素
操作可以让数组奇数偶数不相邻
若无论多少次都无法满足条件 , 则输出-1
,否则输出最少操作数
解题思路 :
首先 , 要满足奇偶不相邻,那么奇数和偶数的个数只差一定<=1
例如: 1 1 1 1 2 2
就一定无法满足
然后我们要讨论n
为奇
还是偶
n为奇时只能出现两种情况 :奇 偶 奇 偶 奇
或者偶 奇 偶 奇 偶
n为偶数时也只能出现两种情况 : 奇 偶 奇 偶 奇 偶
或者偶 奇 偶 奇 偶 奇
知道了最终数组的情况也就好算最小交换次数了
假设初始数组a为 : 奇 偶 偶 奇 奇 偶 奇 奇 偶
那么我们最终的数组a就是 : 奇 偶 奇 偶 奇 偶 奇 偶 奇
以下我用1代表奇
,2代表偶
,如图 :
我们可以轻易地发现 : 地 i 个奇数最终必须到达地 2*i-1
的位置 , 那么这个元素对答案的贡献
就为 |第i个奇数的初始位置 - (2*i-1)|
, 因为 第i个奇数初始位置可能在最终位置的左边或右边,所以要交绝对值
有点像贪心吧 , 我也不知道 , 大概就是这么求的 , 注意n为偶
时 , 要讨论下奇元素在奇位置或者偶位置 , 然后取最小值
AC代码 :
#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py puts("Yes")
#define pn puts("No")
#define pcn putchar('\n')
#define pcs putchar(' ')
#define pc(a) putchar(a)
#define pb(a) push_back(a)
inline void intxt( ){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
}
inline int read( ){
int f = 1,x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
return x;
}
const int maxn=2e5+5;
int n;
int a;
vector<int> ji;//奇元素的位置
vector<int> ou;//偶元素的位置
int jinum;
int ounum;
ll solveji(){//n为奇
ll ans=0;
if( jinum>ounum ){
repi(i,0,jinum-1){
ans+=abs( ji[i]-(i*2+1) );
}
}else{
repi(i,0,ounum-1){
ans+= abs( ou[i]-(i*2+1) );
}
}
return ans;
}
ll solveou(){//n为偶
ll ans=0;
ll tem=0;
repi(i,0,jinum-1){
tem+= abs( ji[i]-(i*2+1) );
}
ans=tem;
tem=0;
repi(i,0,ounum-1){
tem+= abs( ou[i]-(i*2+1) );
}
ans=min(ans,tem);
return ans;
}
int main(){
txt;
CAS{
cin>>n;
ji.clear();
ou.clear();
repi(i,1,n){
a=read();
if(a%2==0){
ou.pb(i);
}else{
ji.pb(i);
}
}
jinum=ji.size();
ounum=ou.size();
if( abs(jinum-ounum)>1 ){//无论如何都不满足
cout<<-1<<endl;
continue;
}
if( n%2==1 ){
cout<<solveji()<<endl;
}else{
cout<<solveou()<<endl;
}
}
return 0;
}
C : Compressed Bracket Sequence
题意 :
输入的a奇位置表示有多少个(
括号,偶位置表示)
括号
求有多少对匹配的括号序列
解题思路 :
咋一看n的范围是1e3 , 那就大胆猜测是n^2
的算法才对 , 也不好解释咋写, 直接看代码吧 , 有点像dp
补题AC代码 :
#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py puts("Yes")
#define pn puts("No")
#define pcn putchar('\n')
#define pcs putchar(' ')
#define pc(a) putchar(a)
#define pb(a) push_back(a)
inline void intxt( ){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
}
inline ll read( ){
ll f = 1,x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
return x;
}
const int maxn=2e3+5;
int n;
ll a[maxn];
ll dp[maxn];//表示以地i个数字')'结尾的个数
int main(){
txt;
cin>>n;
repi(i,1,n){
a[i]=read();
}
ll ans=0,sum,ge;
for(int i=1;i<=n;i+=2){
sum=0;//记录重i+2个位置开始,一直到结尾未被匹配的'('
ge=a[i];//记录i位置未被匹配的'('
for(int j=i+1;j<=n;j++){//遍历须找以i为最后一对'('匹配的括号
if( j%2==0 ){//j为偶表示')',可以开始匹配
if( sum>=a[j] ){//如果中间的'('多于第j个位置的')',那么sum抽一部分与a[j]个')'匹配
sum-=a[j];//中间未匹配'('减少a[j]个
continue;
}
ll tem=a[j]-sum;
sum=0;//昨晚少写了这句 , 一直wa在test 13 , 我太菜了, 中间的'('不够,终于可以用i位置的'('了,那么sum值为0,因为中间的全部被匹配了
if(tem>ge){// ')'比i位置的'('还多
ans+=ge+dp[i-1];
break;
}else if( tem==ge ){// '('与')'一样多
dp[j]=dp[i-1]+1; //用了地j位置的最后一个括号,则更新dp[j]
ans+=ge+dp[i-1];//还要加上i位置前一个位置刚好匹配完最后一个括号的数目
break;
}else{
dp[j]=++;//用到了j位置最后一个')',则更新dp[j]
ans+=tem;
ge-=tem;//地i个位置的'('未使用完
}
}else{//'j'为奇,表示'('
sum+=a[j];
}
}
}
cout<<ans<<endl;
return 0;
}
D : Take a Guess
题意 :
交互题 , 一个长度为n的数组 , 让你猜第k大的数字是什么 , 我们可以询问2*n
次 ,
每次询问可以是以下两种 :
1 , 询问and i j
返回a[i] & a[j]
2 ,询问or i j
返回a[i] | a[j]
解题思路 :
题目给出最多询问2*n
次,那我就尽管用满2*n
就行了 , 我们可以发现
a&b + a|b==a+b
那如果我们这样询问出这样的结果
a[1]+a[2]==x12
,a[2]+a[3]==x23
,a[1]+a[3]==x13
那么就可以解除a了, a[1]=(x12-x23+x13)/2
a[2]=x12-a[1]
a[3]=x13-a[2]
那么后面的数就可以递推求出了
a[4]=x34-a[3]
a[5]=x45-a[4]
…
补题AC代码 :
#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py puts("Yes")
#define pn puts("No")
#define pcn putchar('\n')
#define pcs putchar(' ')
#define pc(a) putchar(a)
#define pb(a) push_back(a)
inline void intxt( ){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
}
inline ll read( ){
ll f = 1,x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
return x;
}
const int maxn=2e3+5;
int AND(int x,int y){
printf("and %d %d\n",x,y);
fflush(stdout);
return (int)read();
}
int OR(int x,int y){
printf("or %d %d\n",x,y);
fflush(stdout);
return (int)read();
}
int n,k;
vector<int> g;
int main(){
//txt;
cin>>n>>k;
int add12=OR(1,2)+AND(1,2);
int add23=OR(2,3)+AND(2,3);
int add31=OR(1,3)+AND(1,3);
int a=(add12-add23+add31)/2;
int b=add12-a;
int c=add31-a;
g.pb(a);
g.pb(b);
g.pb(c);
int pre=c;
repi(i,4,n){
int addxx=OR(i-1,i)+AND(i-1,i);
pre=addxx-pre;
g.pb(pre);
}
sort(g.begin(),g.end());
cout<<"finish "<<g[k-1]<<endl;
return 0;
}