思路:
- 我们最后需要处理数组是非递减的,我们可以尽量处理它相等(显然,至少可以使n-1个数相等)
- 当n是奇数时,我们显然可以凑出a1=a2=...a[n-1],然后比较a[n],因为前面有偶数个数,显然这偶数个数可以一起修改到比a[n]小。
- 当n是偶数时,我们怎么凑,如果最后是a1=a2=...a[n-1]>a[n],我们无法修改<变为>=,因为前面只有奇数个数,无法全部一起修改
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define endl "\n"
const int N = 3e5 + 10;
int a[N];
void mysolve()
{
int n;
cin>>n;
for(int i=1; i<=n; ++i)cin>>a[i];
if(n&1)cout<<"YES"<<endl;
else
{
for(int i=1; i<n-1; ++i)
{
int tmp=a[i+1]-a[i];
a[i+1]-=tmp,a[i+2]-=tmp;
}
if(a[n]>=a[n-1])cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
int32_t main()
{
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
ll t=1;
cin >> t;
while (t--)
{
mysolve();
}
system("pause");
return 0;
}
思路:
- 我们希望询问的时候边都是连通的,不然返回-1就血亏。那么有没有最少的步骤使所有点连通。观察到n+1于n+2就可以使图连通。形成了1->n->2->n-1->n-2->3...这样的链
- 我们显然可以先询问p1到pi(1<i<=n)的距离,显然,距离最大的i(设为k)一定是链的端点
- 因此,我们接下来询问其他数pi到pk的距离,就可以凑出k在左端点时的答案与k在右端点时的答案,使用了2+(n-1)+(n-1)=2n的操作,刚刚好
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
#define int long long
const int N = 2e3 + 10;
int a[N];
void mysolve()
{
int n;
cin>>n;
int p1=1,p2=n;
for(int i=1; i<=n; i+=2)a[i]=p1++,a[i+1]=p2--;//构造链
int x;
char c='+';
cout<<c<<" "<<n+1<<endl;
cin>>x;
cout<<c<<" "<<n+2<<endl;
cin>>x;
int k=1,p=0;
c='?';
for(int i=2; i<=n; ++i)
{
cout<<c<<" "<<1<<' '<<i<<endl;
cin>>x;
if(x>p)p=x,k=i;//找到端点k
}
vector<int>ans1(n+1),ans2(n+1);
ans1[k]=a[1],ans2[k]=a[n];
for(int i=1; i<=n; ++i)if(i!=k)
{
cout<<c<<" "<<k<<" "<<i<<endl;
cin>>x;
ans1[i]=a[1+x];//分别找出k在不同端点形成的序列
ans2[i]=a[n-x];
}
cout<<"!";
for(int i=1; i<=n; ++i)cout<<" "<<ans1[i];
for(int i=1; i<=n; ++i)cout<<" "<<ans2[i];
cout<<endl;
cin>>x;
}
int32_t main()
{
//std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
ll t=1;
cin >> t;
while (t--)
{
mysolve();
}
// system("pause");
return 0;
}