Codeforces Round #624 (Div. 3)(D暴力,E思维+复杂模拟,F线段树)

题目链接

D. Three Integers

题意:给 a b c  你现在可以对这三个数进行+1  -1 操作  问最少操作后使得  a整除b  b整除c

做法:暴力枚举 a和b 就可以了,注意范围  容易被hack

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
int n,m;

ll a,b,c;
ll A,B,C;
ll mx;
void cal(int i,int j,int k)
{
    int t=abs(a-i)+abs(b-j)+abs(k-c);
    if(t<mx){
        mx=t;
        A=i,B=j,C=k;
    }
}
int main()
{
	int _;cin>>_;while(_--)
	{
	    scanf("%lld%lld%lld",&a,&b,&c);
	    mx=0x3f3f3f3f3f3f3f3f;
	    for(ll i=1;i<=2e4;++i){
            for(ll j=i;j<=2e4;j+=i){
                ll x=i,y=j,z=c/y*y;
                if(z>=y) cal(x,y,z);
                z=(c/y+1)*y;
                cal(x,y,z);
            }
	    }
	    printf("%lld\n",mx);
	    printf("%lld %lld %lld\n",A,B,C);
	}
}

E. Construct the Binary Tree

题意:输入n d   代表树的n个节点,每个节点在树上都有一个深度,现在要你构造二叉树  使得所有节点的度之和等于d。

不存在输出NO

思路:思路很简单,先构造一条单链,然后可以考虑从最底下 或者从最上面 取一个点往上移,我这里是从上面选一个点。

代码参考 来自 jiufeng 的提交代码

就是怎么模拟写比较的复杂。

#include<bits/stdc++.h>
#define LL long long
#define PB push_back
#define POP pop_back()
#define PII pair<int,int>
#define ULL unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1),eps=1e-10;
const int maxn=1<<17;
const int N=5e3+10,M=N*40;
int n,d;
int fa[N];
int son[N];
int de[N];//某层的空置位
int dp[N];//dp[i]: i节点在dp[i]层
int main()
{
    de[1]=1;
    int t;
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&d);
        memset(de,0,sizeof(de));
        de[1]=1;
        int s=0;
        for(int i=1;i<=n;i++)s+=i-1;//一条链

        int now=1;
        for(int i=1;i<=n;i++){
            dp[i]=dp[i-1]+1;//下一个节点在i-1的下一层
            de[dp[i]]--;//单链  去掉这层的一个空置位
            
            if(s-(n-i+1)>=d){//i节点往上跳一层,后面的全部往上跳一层,所以是n-i+1
                //printf("i:%d n-i+1:%d d:%d\n",i,n-i+1,d);
                if(de[dp[i]-1]){//因为是往上跳一层,那么看上一层的空置位是否有
                    s-=(n-i+1);
                    de[dp[i]-1]--;//挂在dp[i]-1 层上,所以de[dp[i]-1]的空置位减一
                    de[dp[i]]++;//dp[i]层的空置位+1 抵消掉32行的减一
                    dp[i]--;//i节点成功到达 上一层
                }
            }
            de[dp[i]+1]+=2;
            //cout<<s<<' '<<(n-i+1)<<' '<<dp[i]<<' '<<de[dp[i]+1]<<' '<<de[dp[i]]<<endl;
        }
        //cout<<s<<endl;
        if(s!=d){
            printf("NO\n");
            continue;
        }
        int flag=1;
        memset(son,0,sizeof(son));
        for(int i=2;i<=n;i++){
            fa[i]=0;
            for(int j=1;j<i;j++){
                if(son[j]<2&&dp[i]==dp[j]+1){
                    son[j]++;
                    fa[i]=j;
                    break;
                }
            }
            if(fa[i]==0){
                flag=0;break;
            }
        }
        if(flag==0){
            printf("NO\n");
        }
        else printf("YES\n");
        for(int i=2;i<=n;i++)printf("%d ",fa[i]);printf("\n");
    }
    return 0;
}
/*
1
6 7
0 0 0 0 0 0
0 1 0 3 0 1
2 9 1 2 1 2
8 7 1 3 4 3
1 0 2 2 7 7
0 1 0 0 1 0
0 0 0 0 0 0
*/

F. Moving Points

题意:给定n个位置xi  以及n个速度vi   位置变化为x=vi*t+xi,现在要你求两两点距离和最小,这题容易读成 所有点的t是一致,其实不然  每个点的时间是不一样的,而且每对点的时间也是不一样的。

相当于是求任意两个点最近的距离时的距离和

做法:将x从大到小排个序,按照v 离散化在线段树上查找     x比自己小 v  比自己大的点,因为这些点可以跟这个点重合。

那么答案 就是先求所有点对的距离和-能重合的距离点对距离和

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct node
{
    ll x,v;
}a[N];
ll X[N],len;
int n;
bool cmp(node a,node b)
{
    return a.x<b.x;
}
int getid(ll x)
{
    return lower_bound(X+1,X+1+len,x)-X;
}
ll ans,num,x1,sum;
ll s1[4*N],s2[4*N];
void up(int id,int l,int r,int pos,ll val)
{
    if(l==r){
        s1[id]+=val;
        s2[id]++;
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) up(id<<1,l,mid,pos,val);
    else up(id<<1|1,mid+1,r,pos,val);
    s1[id]=s1[id<<1]+s1[id<<1|1];
    s2[id]=s2[id<<1]+s2[id<<1|1];
}
void qu(int id,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr){
        sum+=s1[id];
        num+=s2[id];
        return ;
    }
    int mid=l+r>>1;
    if(ql<=mid) qu(id<<1,l,mid,ql,qr);
    if(qr>mid) qu(id<<1|1,mid+1,r,ql,qr);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lld",&a[i].x);
    for(int i=1;i<=n;++i) {
        scanf("%lld",&a[i].v);
        X[++len]=a[i].v;
    }
    sort(X+1,X+1+len);
    len=unique(X+1,X+1+len)-X-1;

    sort(a+1,a+1+n,cmp);
    ans=0,num=1,x1=a[1].x,sum=0;
    for(int i=2;i<=n;++i){
        ans+=num*(a[i].x-x1)-sum;
        sum+=a[i].x-x1;
        num++;
    }
    //printf("ans:%lld\n",ans);
    num=0,sum=0;
    for(int i=1;i<=n;++i){
        a[i].v=getid(a[i].v);
        if(i==1){
            up(1,1,len,a[i].v,a[i].x-x1);
            continue;
        }
        num=0,sum=0;
        if(a[i].v<len) qu(1,1,len,a[i].v+1,len);
        ans-=(num*(a[i].x-x1)-sum);
        up(1,1,len,a[i].v,a[i].x-x1);
    }
    printf("%lld\n",ans);

}
发布了498 篇原创文章 · 获赞 66 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/104500027