http://acm.hdu.edu.cn/showproblem.php?pid=5353
3 6 1 0 1 0 0 0 5 1 1 1 1 1 3 1 2 3
NO YES 0 YES 2 2 1 3 2
/**
hdu5353||2015多校联合第六场1001 贪心
题目大意:给定一个序列首尾相连,每两个临的数可以相互给出一个或接受一个1,问是否可以经过一系列转移使所有的数相等
解题思路:枚举第一个数和最后一个数之间的关系(给出一个,接受一个,不处理),然后从前往后判断i和i+1的关系,i少1则从i+1得1,
多1则给i+1一个,正好则跳过。处理的时候就不用考虑i-1了,最后判断是否成功即可。复杂度O(n*3)
*/
#include <string.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
typedef long long LL;
int a[100005],b[100005];
int n,k,p[100005][2];
bool judge()
{
memcpy(b,a,sizeof(a));
for(int i=0;i<n-1;i++)
{
if(b[i]<0)
{
b[i]++;
b[i+1]--;
p[k][0]=i+2;
p[k++][1]=i+1;
}
else if(b[i]>0)
{
b[i]--;
b[i+1]++;
p[k][0]=i+1;
p[k++][1]=i+2;
}
}
for(int i=0;i<n;i++)
{
if(b[i]!=0)return 0;
}
return 1;
}
void print(int flag)
{
if(flag)
{
printf("YES\n%d\n",k);
for(int i=0; i<k; i++)
{
printf("%d %d\n",p[i][0],p[i][1]);
}
}
else
{
puts("NO");
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
LL sum=0;
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
if(sum%n)
{
puts("NO");
continue;
}
sum/=n;
if(n==2&&max(a[1],a[0])-min(a[1],a[0])>2)
{
puts("NO");
continue;
}
for(int i=0; i<n; i++)
{
a[i]-=sum;
}
k=0;
int flag=0;
if(judge())
{
flag=1;
print(1);
}
else
{
k=0;
p[k][0]=n,p[k++][1]=1;
a[n-1]--,a[0]++;
if(judge())
{
flag=1;
print(1);
}
else
{
k=0;
p[k][0]=1,p[k++][1]=n;
a[0]-=2,a[n-1]+=2;
if(judge())
{
flag=1;
print(1);
}
}
}
if(flag==0)
{
print(0);
}
}
return 0;
}
3 6 1 0 1 0 0 0 5 1 1 1 1 1 3 1 2 3
NO YES 0 YES 2 2 1 3 2
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/lvshubao1314/article/details/47341321