Zut_round 7(二分答案)

A

二分最大距离。

/*   Author : Rshs   */
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;

const int MXN = 1e6+5;
int n,c,x[MXN];
bool ck(int g){
    int can=0,dis=0;
    for(int i=2;i<=n;i++){
        dis=dis+x[i]-x[i-1];
        if(dis>=g) dis=0,can++;
    }
    return can>=c-1;
}
int main(){
    while(cin>>n>>c){
        for(int i=1;i<=n;i++)scanf("%d",&x[i]);
        sort(x+1,x+1+n);
        int l=0,r=1e9,ans=-1;
        while(l<=r){
            int md=(l+r)/2;
            if(ck(md)) ans=md,l=md+1;
            else r=md-1;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

B

二分删几个。

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int d[MXN];
char a[MXN],b[MXN];
int lea,leb;
int ck(int cd){
    set<int>st;
    for(int i=1;i<=cd;i++) st.insert(d[i]);
    int pos=1;
    for(int i=1;i<=leb;i++){
        while(pos<=lea&&(st.find(pos)!=st.end()||a[pos]!=b[i])) pos++;
        if(pos==lea+1) return 0;
        pos++;
    }
    return 1;
}
int main(){
    cin>>(a+1)>>(b+1);
    lea=strlen(a+1),leb=strlen(b+1);
    for(int i=1;i<=lea;i++) scanf("%d",&d[i]);
    int l=0,r=lea,ans=-1;
    while(l<=r){
        int mid=(l+r)/2;
        if(ck(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    cout<<ans<<'\n';
    return 0;
}

C

思路

因为飞船速度比公转速度快,所以可以二分。
二分到某个时刻:
计算出卫星p的终态,考虑以下三种情况:
第三种情况是两段切线+一段弧。
在这里插入图片描述

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1.0L);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;

int sx;
double xp,yp,vp,x,y,v,r,rp;
double xy_to_jiao(int xx,int yy){
    double ax=abs(xx),ay=abs(yy);
    if(ax==0&&yy==0) return 0;
    if(ax==0&&yy>0) return pai/2.0;
    if(ax==0&&yy<0) return -pai/2.0;
    if(xx>=0&&yy>=0) return atan(ay/ax);
    if(xx>=0&&yy<=0) return -atan(ay/ax);
    if(xx<=0&&yy>=0) return pai-atan(ay/ax);
    return -(pai-atan(ay/ax));
}
pair <double,double> jiao_to_xy(double Ejiao){
    pair <double,double> re;
    int cc=(int)(Ejiao/(2.0*pai));
    Ejiao=Ejiao-(cc)*(2.0*pai);
    if(Ejiao<-2.0*pai) Ejiao+=(2.0*pai);
    if(Ejiao>2.0*pai) Ejiao-=(2.0*pai);
    if(Ejiao>pai) Ejiao=Ejiao-(2.0*pai);
    if(Ejiao<-pai) Ejiao=Ejiao+(2.0*pai);
    if(Ejiao>=0&&Ejiao<=pai/(2.0)) {
        re.FI=cos(Ejiao)*rp,re.SE=sin(Ejiao)*rp;
        return re;
    }
    if(Ejiao>=pai/2.0&&Ejiao<=pai) {
        Ejiao-=(pai/2.0);
        re.SE=cos(Ejiao)*rp,re.FI=-sin(Ejiao)*rp;
        return re;
    }
    if(Ejiao<=0&&Ejiao>=-pai/(2.0)) {
        Ejiao=-Ejiao;
        re.FI=cos(Ejiao)*rp,re.SE=-sin(Ejiao)*rp;
        return re;
    }
    Ejiao=-Ejiao;
    Ejiao-=(pai/2.0);
    re.SE=-cos(Ejiao)*rp,re.FI=-sin(Ejiao)*rp;
    return re;

}
bool xj(double npx,double npy){ //判断线段和圆有没有相交
    double k=(npy-y)/(npx-x);
    double b=(npx*y-x*npy)/(npx-x);
    double aa=(1.0+k*k),bb=2.0*k*b,cc=b*b-r*r;
    if(bb*bb-4.0*aa*cc<=0) return 0;
    else {
        double x1=(-bb-sqrt(bb*bb-4.0*aa*cc))/(2.0*aa);
        double x2=(-bb+sqrt(bb*bb-4.0*aa*cc))/(2.0*aa);
        if(npx<x1&&x<x1)return 0;
        if(npx>x2&&x>x2)return 0;
    }
    return 1;

}
double dis(double a,double b,double c,double d) {
    return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
bool ck(double tme){
    double Ejiao=xy_to_jiao(xp,yp);
    double Ajiao=vp*tme/(rp);
    Ejiao+=Ajiao;
    pair <double,double> xyzz=jiao_to_xy(Ejiao);
    bool ju=xj(xyzz.FI,xyzz.SE);
    if(ju==0){
        return dis(xyzz.FI,xyzz.SE,x,y)/v<=tme;
    }
    double npx=xyzz.first,npy=xyzz.second;
    double d1=dis(x,y,0,0),d2=dis(npx,npy,0,0);
    double s1=sqrt(d1*d1-r*r);
    double s2=sqrt(d2*d2-r*r);
    double d3=dis(x,y,npx,npy);
    double jj=acos(-(d3*d3-d1*d1-d2*d2)/(2.0*d1*d2))-asin(s1/d1)-asin(s2/d2); //那段弧对应的圆心角
    double dd=s1+s2+jj*r;
    return dd/v<=tme;
}
int main(){
    //cout<<atan(8.1830416/5.7478)*10;
    cin>>sx;xp=sx; cin>>sx;yp=sx; cin>>sx;vp=sx;
    cin>>sx;x=sx; cin>>sx;y=sx; cin>>sx;v=sx; cin>>sx;r=sx;
    rp=sqrt(xp*xp+yp*yp);
    double l=0,r=1e16,ans=-1;
    for(int _=1;_<=200;_++){
        double mid=(l+r)/2.0;
        if(ck(mid)) ans=mid,r=mid;
        else l=mid;
    }
    printf("%.10lf",ans);
    return 0;
}

D

按题意模拟,注意临界状态

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;

int main(){
    int w,h;cin>>w>>h;
    int u1,d1,u2,d2;
    cin>>u1>>d1>>u2>>d2;
    if(d1<d2) swap(d1,d2),swap(u1,u2);
    if(h>=d1){
        while(h>=d1) w+=h,h--;
        w=max(0,w-u1);
    }
    while(h>=d2) w+=h,h--;
    w=max(0,w-u2);
    while(h) w+=h,h--;
    cout<<w<<'\n';
    return 0;
}

E

尽量凑正方形

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;

int main(){
    int n;cin>>n;
    int sq=sqrt(n);
    if(n==sq*sq) return cout<<sq*2,0;
    if(n<=sq*(sq+1)) return cout<<sq*2+1,0;
    cout<<sq*2+2;
    return 0;
}

F

多了就尽量删,少了就用一个*补齐

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;

int main(){
    string s;cin>>s;
    int k;cin>>k;
    int n=s.length();
    int l=0;
    for(int i=0;i<n;i++) if(s[i]!='?'&&s[i]!='*') l++;
    if(k<l){
        int del=l-k;
        string ans;
        for(int i=0;i<n;i++){
            if(i<n-1&&del&&(s[i+1]=='*'||s[i+1]=='?')) i++,del--;
            else if((s[i]!='*'&&s[i]!='?')) ans=ans+s[i];
            //cout<<ans<<'\n';
        }
        if((int)ans.length()==k) cout<<ans<<'\n';
        else cout<<"Impossible"<<'\n';
        return 0;
    }
    int add=k-l;
    string ans;
    for(int i=0;i<n;i++){
        if(i<n-1&&s[i+1]=='*') {
            add++;
            while(add) ans=ans+s[i],add--;
            i++;
        }
        else if((s[i]!='*'&&s[i]!='?')) ans=ans+s[i];
    }
    if((int)ans.length()==k) cout<<ans<<'\n';
    else cout<<"Impossible"<<'\n';
    return 0;
}

G

max搞来搞去,尽量把深度低的结点赋予较大的值,保证所有和最小,注意从v到底一条链全部是-1的情况。

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
vector<int>g[MXN];
int s[MXN];
int mx[MXN];
int a[MXN];
int have[MXN];
void dfs(int now,int pre){
    if(s[now]==-1)mx[now]=INT_MAX;
    else mx[now]=s[now];
    if(s[now]!=-1)have[now]=1;
    for(auto v:g[now]){
        if(v==pre) continue;
        dfs(v,now);
        have[now]=max(have[now],have[v]);
        mx[now]=min(mx[now],mx[v]);
    }
}
void gao(int now,int pre,int pa){
    if(s[now]!=-1&&pa>s[now]) {puts("-1");exit(0);}
    if(s[now]==-1) {
        if(have[now]==0) a[now]=0;
        else a[now]=max(mx[now]-pa,0);
    }
    else a[now]=s[now]-pa;
    for(auto v:g[now]){
        if(v==pre) continue;
        gao(v,now,pa+a[now]);
    }
}
int main(){
    int n;cin>>n;
    for(int i=2;i<=n;i++) {
        int x;scanf("%d",&x);
        g[i].push_back(x);
        g[x].push_back(i);
    }
    for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    dfs(1,-1);
    gao(1,-1,0);
    LL ans=0;
    for(int i=1;i<=n;i++) ans+=(LL)a[i];
    cout<<ans<<'\n';
    return 0;
}

H

思路

观察+证明 符合题意的矩阵:
行两个字母循环排列或者列两个字母循环排列,如:
CTCTC
AGAGA
TCTCT
AGAGA

ATGTG
GCACA
ATGTG
GCACA
ATGTG
得到这个结论后,枚举循环的那个东西,就变成了码农题了。

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
vector<char>a[MXN],ans[MXN],t[MXN];
char f[4]={'A','G','C','T'};
int g[MXN],mi=INT_MAX,u,ss1,ss2;
int n,m;
void  work(int s1,int s2,int uu){
    int ss[2][2]={s1,s2,-1,-1};
    for(int i=0;i<4;i++) {
        if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][0]==-1) ss[1][0]=i;
        else {
            if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][1]==-1) ss[1][1]=i;
        }
    }
    for(int i=0;i<2;i++)for(int j=0;j<2;j++) ss[i][j]=f[ss[i][j]];
    int cnt=0;
    for(int i=1;i<=n;i++){
        int c=0,cc=0;
        for(int j=1;j<=m;j++)c=c+(ss[i%2][j%2]!=a[i][j]);
        swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
        for(int j=1;j<=m;j++)cc=cc+(ss[i%2][j%2]!=a[i][j]);
        swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
        cnt+=min(c,cc);
    }
    if(cnt<mi){
        mi=cnt;
        u=uu;
        ss1=s1,ss2=s2;
    }
}
int main(){

    g['A']=0;g['G']=1;g['C']=2;g['T']=3;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        a[i].push_back('*');
        for(int j=1;j<=m;j++){
            char x;cin>>x;
            a[i].push_back(x);
        }
    }
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++) if(i!=j)work(i,j,0);
    }
    for(int i=1;i<=m;i++){
        t[i].push_back('*');
        for(int j=1;j<=n;j++){
            t[i].push_back(a[j][i]);
        }
    }
    for(int i=1;i<=n;i++)while(SZ(a[i])) a[i].pop_back();
    for(int i=1;i<=m;i++){
        a[i].push_back('*');
        for(int j=1;j<=n;j++){
            a[i].push_back(t[i][j]);
        }
    }
    swap(n,m);
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++) if(i!=j)work(i,j,1);
    }
    swap(n,m);
    int ss[2][2]={ss1,ss2,-1,-1};
    for(int i=0;i<4;i++) {
        if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][0]==-1) ss[1][0]=i;
        else {
            if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][1]==-1) ss[1][1]=i;
        }
    }
    for(int i=0;i<2;i++)for(int j=0;j<2;j++) ss[i][j]=f[ss[i][j]];
    if(u==0){
        for(int i=1;i<=n;i++){
            int c=0,cc=0;
            for(int j=1;j<=m;j++)c=c+(ss[i%2][j%2]!=a[j][i]);
            swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            for(int j=1;j<=m;j++)cc=cc+(ss[i%2][j%2]!=a[j][i]);
            swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            if(c<cc){
                for(int j=1;j<=m;j++)cout<<(char)ss[i%2][j%2];
            }
            else {
                swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
                for(int j=1;j<=m;j++)cout<<(char)ss[i%2][j%2];
                swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            }
            puts("");
        }
    }
    else {
        for(int i=1;i<=m;i++){
            int c=0,cc=0;
            for(int j=1;j<=n;j++)c=c+(ss[i%2][j%2]!=a[i][j]);
            swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            for(int j=1;j<=n;j++)cc=cc+(ss[i%2][j%2]!=a[i][j]);
            swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            if(c<cc){
                for(int j=1;j<=n;j++) ans[j].push_back(ss[i%2][j%2]);
            }
            else {
                swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
                for(int j=1;j<=n;j++) ans[j].push_back(ss[i%2][j%2]);
                swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
            }
        }
        for(int i=1;i<=n;i++) {
            for(auto j:ans[i]) cout<<j;
            puts("");
        }
    }
    return 0;
}

I

树上博弈+线段树。
对于某一个结点V,他能得到的最大饼干数:
先将总时间减去到V的路径的两倍,再取路径上的若干吃的快的饼干,也就是前小(这部分可以用线段树维护)
然后考虑对弈情况:
Vasya肯定剪可以得到较大答案的边,所以后续遍历取儿子结点第二大的答案。
这里注意一个wa点:可能在根节点不动,只吃根节点的饼干。
(我也不知道为什么我要一开始写二分,还nm超时了(估计就超了2~3倍?))

/*   Author : Rshs   */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
LL n,tme,x[200005],t[200005],d[200005],can[200005],dp[MXN];
vector<int>g[MXN];
LL S[MXN*4],C[MXN*4],MXT=1e6;

void update(int pos,int l,int r,int root,LL c){
    if(l==r){
        C[root]+=c;S[root]+=(c*(LL)l);
        return ;
    }
    int mid=(l+r)/2;
    if(pos<=mid) update(pos,l,mid,root<<1,c);
    else update(pos,mid+1,r,root<<1|1,c);
    C[root]=C[root<<1]+C[root<<1|1];
    S[root]=S[root<<1]+S[root<<1|1];
}
LL query(int l,int r,int root,LL have){
    if(l==r){
        return min(have/(LL)l,C[root]);
    }
    int mid=(l+r)/2;
    if(S[root<<1]>have) return query(l,mid,root<<1,have);
    return query(mid+1,r,root<<1|1,have-S[root<<1])+C[root<<1];
}

void dfs(int now,int pre,LL co){
    update(t[now],1,MXT,1,x[now]);
    can[now]=query(1,MXT,1,tme-co);
    for(auto i:g[now]){
        if(i==pre)continue;
        dfs(i,now,co+d[i]*2LL);
    }
    update(t[now],1,MXT,1,-x[now]);
}
void gao(int now,int pre){
    if(SZ(g[now])==1) {
        dp[now]=can[now];return;
    }
    multiset<LL>st;
    for(auto i:g[now]){
        if(i==pre)continue;
        gao(i,now);
        st.insert(dp[i]);
    }
    st.erase(--st.end());
    if(SZ(st)!=0) dp[now]=max(can[now],*(--st.end()));
    else dp[now]=can[now];
}

int main(){
    cin>>n>>tme;
    for(int i=1;i<=n;i++) {int sa;scanf("%d",&sa);x[i]=sa;}
    for(int i=1;i<=n;i++) {int sa;scanf("%d",&sa);t[i]=sa;}
    for(int i=2;i<=n;i++){
        int sa;scanf("%d",&sa); g[sa].push_back(i);g[i].push_back(sa);
        int sb;scanf("%d",&sb); d[i]=sb;
    }
    dfs(1,-1,0);
    LL ans=min(tme/t[1],x[1]);
    for(auto i:g[1]){
        gao(i,1);
        ans=max(ans,dp[i]);
    }
    cout<<ans<<'\n';
    return 0;
}
/*
5 4
1 5 1 7 7
1 3 1 2 2
1 1
1 1
2 0
2 0
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值