思路:有奇偶数同时存在YES,只有奇数是n是奇数为YES,否则NO
#include
#define MAXN 2005
using namespace std;
int n,t;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
bool flag1 = false,flag2 = false;
int tmp;
for(int i = 1; i<= n;++i)
{
scanf("%d",&tmp);
if(tmp&1)
flag1 = true;
else
flag2 = true;
}
if((flag1 && flag2) || (flag1 && (n&1)))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
思路:超过10元不断花10元就好
#include
#define ll long long
using namespace std;
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ll ans = 0;
while(n >= 10)
{
ans += n/10*10;
n = n% 10 + n / 10;
}
ans += n;
printf("%lld\n",ans);
}
return 0;
}
思路:受限取的一段LR和UD的数量分别相同将L看成1,R看成-1,U看成1,D看成-1,分别求LR,UD的前缀和,如果两个位置LR和UD的前缀和都相等,那么它们中间一段就满足条件,因为存在负数,先加上一个数让他们都变为正数,然后记sum = LR前缀和INF+UD前缀和INF,这样sum相等时两个前缀和就分别相等了,然后对于每个下标处的sum值算出上一个sum相等地方的位置就好
#include
#define MAXN 200005
#define ll long long
using namespace std;
char s[MAXN];
int sum1[MAXN],sum2[MAXN],sum[MAXN];
unordered_map mp;
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%s",&n,s+1);
mp.clear();
sum1[0] = sum2[0] = n+1;
for(int i = 1;i <= n;++i)
{
sum1[i] = sum1[i-1],sum2[i] = sum2[i-1];
if(s[i] == 'U')
++sum2[i];
else if(s[i] == 'D')
--sum2[i];
else if(s[i] == 'R')
++sum1[i];
else
--sum1[i];
sum[i] = 1ll*2*MAXN*sum1[i]+sum2[i];
}
sum[0] = 1ll*2*MAXN*sum1[0]+sum2[0];
int ans = MAXN,id1,id2;
for(int i = 0;i <= n;++i)
{
if(mp.count(sum[i]) && ans > (i-mp[sum[i]]))
{
ans = i-mp[sum[i]];
id1 = i;
id2 = mp[sum[i]];
}
mp[sum[i]] = i;
}
if(ans == MAXN)
printf("-1\n");
else
printf("%d %d\n",id2+1,id1);
}
return 0;
}
思路:直接算出每个怪兽处要得分得跳多少次,然后排个序就好
#include
#define MAXN 200005
using namespace std;
int n,a,b,k,h[MAXN],v[MAXN];
int main()
{
while(~scanf("%d%d%d%d",&n,&a,&b,&k))
{
for(int i = 1;i <= n;++i)
{
scanf("%d",&h[i]);
h[i] %= (a+b);
if(h[i] == 0)
h[i] = a+b;
v[i] = h[i]/a;
if(h[i] % a == 0)
--v[i];
}
sort(v+1,v+n+1);
int id = 1;
while(k >= v[id] && id <= n)
k-=v[id],++id;
printf("%d\n",id-1);
}
return 0;
}
思路:直接见E2
#include
#define MAXN 200005
using namespace std;
int n,vis[26][MAXN],pre[26][MAXN],ans[MAXN];
char s[MAXN];
inline int find(int id,int x)
{
return x == pre[id][x] ? x : pre[id][x] = find(id,pre[id][x]);
}
int main()
{
scanf("%d%s",&n,s+1);
for(int i = 0;i < 26;++i)
{
for(int j = 0;j <= n;++j)
pre[i][j] = j;
}
int mx = 1;
for(int i = 1;i <= n;++i)
{
int id = s[i] - 'a';
ans[i] = find(id,0)+1;
mx = max(mx,ans[i]);
for(int j = 0;j < id;++j)
{
if(!vis[j][ans[i]])
{
vis[j][ans[i]] = 1;
pre[j][ans[i]-1] = ans[i];
}
}
}
if(mx <= 2)
{
printf("YES\n");
for(int i = 1;i <= n;++i)
printf("%d",ans[i]-1);
}
else
printf("NO");
return 0;
}
思路:很明显每个字母要和前面所有比他大的进行交换,即要和前面所有比他大的字母染的颜色不同(将这些字母的颜色集合称为S),很明显颜色标号越小越好,即染成S中未出现的最小标号,直接维护26个并查集,第i个并查集维护出’a’+i对应的集合S,而每一个数的父亲一开始为自身,当x被染色后,x-1的父亲变为x,然后每次查询相应并查集0的父亲即为0开始连续一段中最大的颜色编号,这个编号加一即为需要染成的颜色
赛后看了下别人的,似乎前面比它大的字母的颜色标号会刚好覆盖1 ~ mx,直接取mx+1就好
#include
#define MAXN 200005
using namespace std;
int n,vis[26][MAXN],pre[26][MAXN],ans[MAXN];
char s[MAXN];
inline int find(int id,int x)
{
return x == pre[id][x] ? x : pre[id][x] = find(id,pre[id][x]);
}
int main()
{
scanf("%d%s",&n,s+1);
for(int i = 0;i < 26;++i)
{
for(int j = 0;j <= n;++j)
pre[i][j] = j;
}
int mx = 1;
for(int i = 1;i <= n;++i)
{
int id = s[i] - 'a';
ans[i] = find(id,0)+1;
mx = max(mx,ans[i]);
for(int j = 0;j < id;++j)
{
if(!vis[j][ans[i]])
{
vis[j][ans[i]] = 1;
pre[j][ans[i]-1] = ans[i];
}
}
}
printf("%d\n",mx);
for(int i = 1;i <= n;++i)
printf("%d ",ans[i]);
return 0;
}