Codeforces Round #698 (Div. 2) 题解
A
给你一个单调不减的序列,问最多能分割成几个严格单调的子序列。
注意到序列个数与出现次数最多的元素有关,直接统计即可。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=110;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
int n,T,cnt[N],ans,x;
int main(int argc, char const *argv[])
{
read(T);
while (T--)
{
read(n);
ans=-1;
for (int i=1;i<=n;++i) cnt[i]=0;
for (int i=1;i<=n;++i)
{
read(x);
++cnt[x];
ans=max(ans,cnt[x]);
}
printf("%d\n",ans);
}
return 0;
}
B
给你一个数\(q\),问能否拆分成多个包含数码\(d\)的数的和。
注意到当\(q\)大于\(10*d\)时,可以将\(q\)拆分成一个个位为\(d\)的两位数和一个十位为\(d\)的数(或者\(q\)本身合法)。当\(q\)小于\(10*d\)时,可以被拆分成一堆\(d\)和一个\(10\)的倍数,判断一下即可。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
int T,q,d,x;
int main(int argc, char const *argv[])
{
read(T);
while (T--)
{
read(q),read(d);
for (int i=1;i<=q;++i)
{
read(x);
int flag=0;
for (int j=1;j<=9;++j)
{
if (x-j*d<0) break;
if ((x-j*d)%10==0)
{
flag=1;
break;
}
}
if (x>=10*d) flag=1;
if (flag) printf("YES\n"); else printf("NO\n");
}
}
return 0;
}
C
给出一个数轴上每个点到其他点的距离和,判断是否存在合法的且关于原点对称的长度为\(2*n\)的序列。
排序去重后只要考虑正半轴的部分,距离越小的点离原点越近。做差分之后相邻的两个点之间相差了\(2*i\)个\(d_i\)。
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
const int N=200010;
LL T,n,len,a[N],b[N],d;
int main(int argc, char const *argv[])
{
read(T);
while (T--)
{
read(n);
for (int i=1;i<=(n<<1);++i) read(a[i]);
sort(a+1,a+n*2+1);
len=unique(a+1,a+n*2+1)-a-1;
if (len!=n)
{
printf("NO\n");
continue;
}
int flag=0;
d=0,b[1]=0;
for (int i=1;i<n;++i)
{
if ((a[i+1]-a[i])%(i<<1))
{
flag=1;
break;
}
b[i]=(a[i+1]-a[i])/(i<<1);
}
if (flag)
{
printf("NO\n");
continue;
}
for (int i=2;i<n;++i) d+=(b[i]+=b[i-1]);
d+=b[1];
if (a[1]-d*2>0 && (a[1]-d*2)%(n*2)==0) printf("YES\n"); else printf("NO\n");
}
return 0;
}
D
在黑板上有\(n\)个各不相同的整数\(a_i\),你可以任取两个数\(x\)和\(y\),写上\(2x-y\),且不擦掉\(x\)和\(y\),问一系列操作后能否获得给定的数\(k\)。
注意到\(2x-y\)可以写成\(2(x-y)+y\),一系列操作后得到的数一定可以写成\(a_t\)加上\(a_i-a_j\)的线性组合,而\(a_i-a_j\)可以用\(a_i-a_{i+1}\)线性表示。枚举\(a_t\)用裴蜀定理判断即可。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define LL long long
using namespace std;
const int N=200010;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
LL gcd(LL x,LL y) { return (!y)?x:gcd(y,x%y); }
LL n,k,T,x,y,a[N],b[N],d;
int main(int argc, char const *argv[])
{
read(T);
while (T--)
{
read(n),read(k);
for (int i=1;i<=n;++i) read(a[i]);
for (int i=1;i<n;++i) b[i]=a[i+1]-a[i];
d=b[1];
for (int i=2;i<n;++i) d=gcd(d,b[i]);
int flag=0;
for (int i=1;i<=n;++i) if ((k-a[i])%d==0) { flag=1; break; }
printf(flag?"YES\n":"NO\n");
}
return 0;
}
E
给你一个长度为\(n\)的\(01\)串和\(q\)个询问,每次询问时要保证区间内仅有\(0\)或\(1\),询问完后可以改变区间内严格小于\(1/2\)区间长度个数,问能否将给定串变成目标串。
倒着做,线段树维护区间覆盖区间和,贪心地去选\(0\)还是\(1\)。看最后能否将目标串还原成给定串。记得清零。
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define LL long long
#define NO { printf("NO\n"); return; }
using namespace std;
const int N=200010;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
struct Q
{
int l,r;
}b[N];
int n,q,T;
char s1[N],s2[N];
struct node
{
int sum;
int delta;//1 or 2 (&1)
};
node a[N<<2];
inline void pushup(int cur) { a[cur].sum=a[cur<<1].sum+a[cur<<1|1].sum; }
inline void pushdown(int cur,int l,int r)
{
int mid=l+r>>1;
a[cur<<1].sum=(mid-l+1)*(a[cur].delta&1),a[cur<<1].delta=a[cur].delta;
a[cur<<1|1].sum=(r-mid)*(a[cur].delta&1),a[cur<<1|1].delta=a[cur].delta;
a[cur].delta=0;
}
void build(int cur,int l,int r)
{
a[cur].sum=a[cur].delta=0;
if (l<r)
{
int mid=l+r>>1;
build(cur<<1,l,mid),build(cur<<1|1,mid+1,r);
pushup(cur);
}
else a[cur].sum=s2[l]-'0';
}
int inquire(int cur,int l,int r,int L,int R)
{
if (L<=l && r<=R) return a[cur].sum;
if (a[cur].delta) pushdown(cur,l,r);
int ans=0,mid=l+r>>1;
if (L<=mid) ans+=inquire(cur<<1,l,mid,L,R);
if (R>mid) ans+=inquire(cur<<1|1,mid+1,r,L,R);
return ans;
}
void update(int cur,int l,int r,int L,int R,int x)
{
if (L<=l && r<=R)
{
a[cur].sum=(r-l+1)*x;
a[cur].delta=2-x;
return;
}
if (a[cur].delta) pushdown(cur,l,r);
int mid=l+r>>1;
if (L<=mid) update(cur<<1,l,mid,L,R,x);
if (R>mid) update(cur<<1|1,mid+1,r,L,R,x);
pushup(cur);
}
void work()
{
read(n),read(q);
scanf("%s",s1+1),scanf("%s",s2+1);
build(1,1,n);
for (int i=1;i<=q;++i) read(b[i].l),read(b[i].r);
for (int i=q;i;--i)
{
int l=b[i].l,r=b[i].r,t=inquire(1,1,n,l,r);
if ((t<<1)==r-l+1) NO
if ((t<<1)<r-l+1) update(1,1,n,l,r,0);
else update(1,1,n,l,r,1);
}
for (int i=1;i<=n;++i) if (s1[i]-'0'!=inquire(1,1,n,i,i)) NO
printf("YES\n");
}
int main(int argc, char const *argv[])
{
read(T);
while (T--)
work();
return 0;
}
F
在一个平面上给你\(n\)个点,问你是否存在一个合法排列,使相邻的两两组成的向量之间的夹角严格大于\(90^{\circ}\)。
注意到点\(A_{i},A_{i+1},A_{i+2}\)构成的三角形中只能有一个钝角。故可以通过调整顺序使得其合法。于是可以一个一个将点加入序列,并逐步调整。
#include<cstdio>
#include<algorithm>
#include<cctype>
#define LL long long
using namespace std;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
const int N=5010;
struct PI
{
LL x,y;
PI (LL xx=0,LL yy=0):x(xx),y(yy) {}
LL operator * (PI p) { return x*p.x+y*p.y; }
PI operator + (PI p) { return PI(x+p.x,y+p.y); }
PI operator - (PI p) { return PI(x-p.x,y-p.y); }
};
LL c[N],x,y,n;
PI a[N];
int main(int argc, char const *argv[])
{
read(n);
for (int i=1;i<=n;++i)
{
c[i]=i;
read(x),read(y);
a[i]=PI(x,y);
}
for (int i=3;i<=n;++i)
for (int j=i;j>=3;--j)
if ((a[j]-a[j-1])*(a[j-2]-a[j-1])<=0)
swap(a[j],a[j-1]),swap(c[j],c[j-1]); else break;
for (int i=1;i<=n;++i) printf("%lld ",c[i]);
return 0;
}

浙公网安备 33010602011771号