Codeforces Round #358 (Div. 2)

本文解析了三个算法问题:Alyona与树的DFS算法,Alyona与字符串的DP算法,Alyona与三角形的最大三角形寻找及凸包算法。提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Alyona and the Tree

  dfs。看看哪些节点需要删去,删掉它为根的子树即可。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 100010;

vector<int> sons[maxn];
vector<ll> ew[maxn];

ll vw[maxn];

int ans = 0;

void dfs(int u,ll MAXdist,bool flag){
    int sz = sons[u].size();
    for(int i=0;i<sz;i++){
        int v = sons[u][i];
        ll newMax = MAXdist + ew[u][i];
        if(MAXdist<0){
            newMax = ew[u][i];
        }
        bool newFlag = 0;
        if(flag || newMax > vw[v]){
            ans++;
            newFlag = 1;
        }
        dfs(v,newMax,flag || newFlag);
    }
} 

int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%I64d",&vw[i]);
    }   

    for(int i=1;i<n;i++){
        int u;
        ll ww;
        int v=i+1;
        scanf("%d%I64d",&u,&ww);
        sons[u].push_back(v);
        ew[u].push_back(ww);
    }

    dfs(1,-1,0);

    cout<<ans<<endl;

    return 0;
}

D. Alyona and Strings

  进行2次dp,第一次求出以每个位置结尾的最长公共子串;第二次状态为 dp(i,j,k) ,即到位置 i j为止,分为 k 段的答案。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

char a[1010];
char b[1010];

int num[1010][1010];

int n,m,k;

void LCS(){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            if(a[i-1]==b[j-1]){
                num[i][j]=num[i-1][j-1]+1;
            }
        }
    }
}

int dp[1010][1010][15];

int main(){
    cin>>n>>m>>k; 

    scanf("%s",a);
    scanf("%s",b);

    LCS();

    int ans = 0;
    for(int kk=1;kk<=k;kk++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dp[i][j][kk] = max(dp[i][j][kk],dp[i-num[i][j]][j-num[i][j]][kk-1] + num[i][j]);
                dp[i][j][kk] = max(dp[i][j][kk],dp[i-1][j][kk]);
                dp[i][j][kk] = max(dp[i][j][kk],dp[i][j-1][kk]);
                dp[i][j][kk] = max(dp[i][j][kk],dp[i-1][j-1][kk]);
                if(dp[i][j][kk] >ans){
                    ans = dp[i][j][kk];
                }
            }
        }
    }

    for(int i=1;i<=k;i++){
        ans = max(ans,dp[n][m][i]);
    }
    cout<<ans<<endl;

    return 0;
} 

E. Alyona and Triangles

  找出n个点可以组成的最大三角形,以它为中心,在3条边方向分别添上与之全等的三角形补成一个大三角形,一定满足题意,可用反证法证明。
  具体做法是,首先求凸包(注意凸包边上出现的点不能漏),最大三角形一定出现在凸包的点上。然后,枚举第一个点,按顺序枚举第二个点,第三个点随着第二个点的移动单调,利用这个性质在 O(n2) 的时间内得到最大三角形。

#include <bits/stdc++.h>

using namespace std;

#define ll long long

typedef double TYPE;

struct POLY{
    int n;
    TYPE *x;
    TYPE *y;

    POLY():n(0),x(NULL),y(NULL){};

    POLY(int _n,const TYPE *_x,const TYPE * _y){
        n = _n;
        x = new TYPE[n+1];
        memcpy(x,_x,n*sizeof(TYPE));
        x[n] = _x[0];
        y = new TYPE[n+1];
        memcpy(y,_y,n*sizeof(TYPE));
        y[n] = _y[0];
    }
}poly;


struct POINT{
    TYPE x;
    TYPE y;
    POINT():x(0),y(0){
    }
    POINT(TYPE _x,TYPE _y):x(_x),y(_y){
    }
    POINT operator-(POINT other){  
        return POINT(x-other.x,y-other.y);  
    }
    POINT operator+(POINT other){  
        return POINT(x+other.x,y+other.y);  
    }  
};

TYPE Cross(const POINT &a,const POINT &b,const POINT &o){
    return (a.x-o.x)*(b.y-o.y) - (b.x-o.x)*(a.y-o.y);
}

TYPE Distance(const POINT &a, const POINT &b){
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

POLY ConvexHull(const POINT *Set, int n){
    POINT *points = new POINT[n];
    memcpy(points, Set,n*sizeof(POINT));
    TYPE *X = new TYPE[n];
    TYPE *Y = new TYPE[n];
    int i,j,k = 0, top = 2;
    for(i = 1;i<n;i++){
        if((points[i].y<points[k].y) ||
                ((points[i].y == points[k].y) && 
                (points[i].x<points[k].x))){
            k = i;          
        }
    }

    swap(points[0],points[k]);

    for(i = 1;i<n-1;i++){
        k=i;
        for(j = i+1;j<n;j++){
            if( (Cross(points[j],points[k],points[0])>0) ||
                    ((Cross(points[j],points[k],points[0]) == 0) &&
                    (Distance(points[0],points[j])<Distance(points[0],points[k])))){
                k = j;  
            }
        }
        swap(points[i],points[k]);
    }

    X[0] = points[0].x; Y[0] = points[0].y;
    X[1] = points[1].x; Y[1] = points[1].y;
    X[2] = points[2].x; Y[2] = points[2].y;

    for(i = 3;i<n;i++){
        while(Cross(points[i],POINT(X[top],Y[top]),POINT(X[top-1],Y[top-1]))>=0){
            top--;
        }
        ++top;
        X[top] = points[i].x;
        Y[top] = points[i].y;
    }

    delete[] points;
    POLY poly(++top,X,Y);
    delete[] X;
    delete[] Y;

    return poly;
}

POINT pts[5555];

int main(){  
    int n,s;  
    cin>>n>>s; 

    for(int i=0;i<n;i++){  
        scanf("%lf %lf",&pts[i].x,&pts[i].y);  
    }

    poly = ConvexHull(pts , n);
    n=poly.n;

    int a[3];

    for(int i=0;i<n;i++){
        pts[i] = POINT(poly.x[i],poly.y[i]);
    }

    int j=1,k=0;  
    double ans=0;  
    for(int i=0;i<n;i++)  { 
        j=(i+1)%n;  
        k=(j+1)%n;  
        while(fabs(Cross(pts[i],pts[j],pts[k]))<fabs(Cross(pts[i],pts[j],pts[(k+1)%n]))) k=(k+1)%n; 

        while(j!=i&&k!=i)  { 
            if(fabs(Cross(pts[i],pts[j],pts[k])) > ans){
                ans = fabs(Cross(pts[i],pts[j],pts[k]));
                a[0] = i;
                a[1] = j;
                a[2] = k;
            }

            while(fabs(Cross(pts[i],pts[j],pts[k]))<fabs(Cross(pts[i],pts[j],pts[(k+1)%n])))  
                 k=(k+1)%n;  
            j=(j+1)%n;  
        }  
    } 


        POINT b[3];
        b[0] = pts[a[1]] + (pts[a[2]]-pts[a[0]]);
        b[1] = pts[a[0]] + (pts[a[2]]-pts[a[1]]);
        b[2] = pts[a[0]] + (pts[a[1]]-pts[a[2]]);

            for(int i=0;i<3;i++){
                cout<<(int)b[i].x<<" "<<(int)b[i].y<<endl;
            }
            return 0;


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值