Codeforces Round #670(Div.2) 문제 해결
54862 단어 시합
A
간단한 욕심은 바로 코드에 들어간다.
#include
#include
#include
#include
using namespace std;
#define maxn 110
int T,n,a[maxn],b[maxn];
int main()
{
scanf("%d",&T);while(T--)
{
scanf("%d",&n);
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[a[i]]++;
int ans=0,now=0;
while(b[now]>1)ans+=2,now++;
while(b[now]>0)ans++,now++;
printf("%d
",ans);
}
}
B
mi[i],ma[i]mi[i],ma[i]mi[i],ma[i]는 현재 위치까지 일일이 열거하고 ii의 개수로 곱할 수 있는 최소와 최대 수를 나타낸다. 그들의 이동은 mi[i-1],ma[i-1]mi[i-1],ma[i-1]mi[i-1],ma[i-1],ma[i-1]와 관련되어 마구잡이로 하면 된다.
코드는 다음과 같습니다.
#include
#include
#include
#include
using namespace std;
#define maxn 200010
#define ll long long
int T,n;
ll a[maxn],mi[10],ma[10];
int main()
{
scanf("%d",&T);while(T--)
{
scanf("%d",&n);ll ans=-1e18;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=5;i++)mi[i]=1e18,ma[i]=-1e18;
for(int i=1;i<=n;i++){
for(int j=5;j>=2;j--)if(i>=j){
mi[j]=min(mi[j],min(mi[j-1]*a[i],ma[j-1]*a[i]));
ma[j]=max(ma[j],max(mi[j-1]*a[i],ma[j-1]*a[i]));
}
mi[1]=min(mi[1],a[i]);
ma[1]=max(ma[1],a[i]);
ans=max(ans,ma[5]);
}
printf("%lld
",ans);
}
}
C
처음에 몇 개의 중심을 살펴보고 두 개가 있다면 그 중 한 개의 중심의 한 잎을 다른 중심에 주면 중심이 유일한 것이다.
코드는 다음과 같습니다.
#include
#include
#include
#include
using namespace std;
#define maxn 200010
#define pb push_back
int T,n;
vector<int>e[maxn];
int size[maxn],mson[maxn],rt,rt_;
void dfs(int x,int fa){
size[x]=1;mson[x]=0;
for(int y:e[x])if(y!=fa){
dfs(y,x);size[x]+=size[y];
if(size[y]>mson[x])mson[x]=size[y];
}
if(n-size[x]>mson[x])mson[x]=n-size[x];
if(mson[x]<mson[rt])rt=x,rt_=0;
else if(mson[x]==mson[rt])rt_=x;
}
void dfs1(int x,int fa,int &l,int &f){
int son=e[x].size()-1;
if(!son)l=x,f=fa;
else if(e[x][0]!=fa)dfs1(e[x][0],x,l,f);
else dfs1(e[x][1],x,l,f);
}
int main()
{
scanf("%d",&T);while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)e[i].clear();
for(int i=1,x,y;i<n;i++)scanf("%d %d",&x,&y),e[x].pb(y),e[y].pb(x);
mson[rt=rt_=0]=1e9;dfs(1,0);
if(rt_){
int l,f;
dfs1(rt,rt_,l,f);
printf("%d %d
%d %d
",l,f,l,rt_);
}else{
printf("%d %d
%d %d
",1,e[1][0],1,e[1][0]);
}
}
}
D
먼저 하나의 서열을 어떻게 하강하지 않고 상승하지 않는 서열로 분해할 것인가를 고려해라.감법만 해서 이 서열을 상승하지 않는 서열로 바꾸는 것을 고려하면, 최대치가 이전 서열의 최소치와 같을 때까지 모든 극장 불하강 서브 세그먼트를 전체적으로 줄여야 한다.
그러면 각 위치에서 뺀 값은 반드시 내려가지 않는 서열을 형성할 수 있고 두 서열은 구조가 끝난다.그리고 그들의 최대치를 최소화해야 한다. a, b, a, b는 두 서열의 현재 최대치이다. 분명히 큰 것은 전체적으로 줄이고 작은 것은 전체적으로 증가하며 최대치는\lceil\rac {a+b} 2\rceil\2a+b⌉이다.
상승하지 않는 서열의 최대치는 분명히 첫 번째 서열의 수이고 하락하지 않는 서열의 최대치는 이 서열의 마지막 서열의 수이다. 원래의 서열을 bb수조로 나누면 마지막 서열의 수는 모두 b[i]>0b[i]>0b[i]>0의 b[i]b[i]b[i]b[i]b[i]의 합을 만족시키는 것이다.
수정하면 바로 차점수 그룹을 수정하여 O(1)O(1)O(1)완성할 수 있습니다.
코드는 다음과 같습니다.
#include
#include
#include
#include
using namespace std;
#define maxn 100010
#define ll long long
int n,m;
ll a[maxn],b[maxn],sum=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i]-a[i-1];
for(int i=2;i<=n;i++)if(b[i]>0)sum+=b[i];
printf("%lld
",(ll)ceil(1.0*(b[1]+sum)/2.0));
scanf("%d",&m);
for(int i=1,l,r,x;i<=m;i++){
scanf("%d %d %d",&l,&r,&x);
if(l>1&&b[l]>0)sum-=b[l];
b[l]+=x;
if(l>1&&b[l]>0)sum+=b[l];
if(r<n){
r++;
if(b[r]>0)sum-=b[r];
b[r]-=x;
if(b[r]>0)sum+=b[r];
}
printf("%lld
",(ll)ceil(1.0*(b[1]+sum)/2.0));
}
}
E
10510^5 105 이내의 질량수가 9592 9592 9592개라는 것을 발견하였는데, 이는 각 질량수가 약 11번만 조작할 수 있음을 의미한다.
먼저 n\sqrtn 이내의 질수를 매거하고, xx질인수를 분해한 후 이 질수의 출현 횟수는 111을 초과할 수 있으며, 매번 폭력 BBB가 매거한 pppp를 매거한 다음에 p,p2,p3을 매거한다.p,p^2,p^3,... p,p2,p3,... 차례대로 A A 조작을 하면 그들의 출현 횟수를 확정할 수 있다.
다시 n\sqrtnn보다 큰 질수를 고려하면 이 질수는 가장 많이 한 번 나타나고 이때 n\sqrtn~nn 범위 내에 합수가 없다(xxx 제외).
먼저 xxx는 n\sqrtn보다 큰 질수이고 매번 BBB의 반수를 고려한다. 만약에 BB가 끝난 후에 A1A~1A1에게 물어보면 예상한 것과 다르다. 그러면 이 중에는 반드시 xxx가 있다. 각 AA는 한 번에 찾을 수 있다. 그렇지 않으면 다른 반에서 위의 조작을 반복하면 이런 조작에 필요한 횟수가 대략
회라는 것을 알 수 있다.다시 xxx가 n\sqrtn보다 큰 질수를 인자로 가지고 있으나 질수가 아닌 경우를 고려하면 위에서 BBB를 가지는 과정에서 어떤 BB가 222를 냈는지 확인해 보면 된다.
코드는 다음과 같습니다.
#include
#include
#include
#include
using namespace std;
#define maxn 100010
int n,ans=1;
int prime[maxn],t=0;
bool v[maxn];
void work(){
for(int i=2;i<=n;i++){
if(!v[i])prime[++t]=i;
for(int j=1;j<=t&&i*prime[j]<=n;j++){
v[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
int ask(char x,int y){
printf("%c %d
",x,y);fflush(stdout);
if(x!='C'){
int re;scanf("%d",&re);return re;}
else exit(0);
}
int st=1,sum;
void solve(int l,int r){
int mid=l+r>>1;
for(int i=l;i<=mid;i++){
if(ask('B',prime[i])>1)ask('C',ans*prime[i]);
sum--;
}
if(ask('A',1)!=sum){
for(int i=l;i<=mid;i++)
if(ask('A',prime[i]))ask('C',ans*prime[i]);
}
if(mid<r)solve(mid+1,r);
}
int main()
{
scanf("%d",&n);work();sum=n;
for(;st<=t&&prime[st]*prime[st]<=n;st++){
int &x=prime[st];
sum-=ask('B',x);
if(ask('A',1)!=sum){
sum++;
for(int j=x;j<=n&&ask('A',j);j*=x)ans*=x;
}
}
if(st<=t)solve(st,t);
ask('C',ans);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Codeforces Round #670(Div.2) 문제 해결먼저 하나의 서열을 어떻게 하강하지 않고 상승하지 않는 서열로 분해할 것인가를 고려해라.감법만 해서 이 서열을 상승하지 않는 서열로 바꾸는 것을 고려하면, 최대치가 이전 서열의 최소치와 같을 때까지 모든 극장 불하강...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.