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);

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章