【Author : DS】(CUGB 120920训练)NCPC 2009 5AC

前言:

因为跟老婆缠绵,迟到了将近十分钟,不过还是依然很淡然地坐下来看题。英文已经看不懂了啊看不懂了啊- -


A

很水的模拟题,随便搞,不说了


B

一眼就看出来了并查集,只用把一个组的人的钱都加到祖宗的枝杈上面,看是不是>=0 就可以了。好水- -

namespace ufset{
          const int N=10001;
          int fa[N],rank[N];

          void init() { for (int i=0;i<N;++i) fa[i]=i,rank[i]=0; }
          int find(int x){
              int r=x,y;
              while (fa[r]!=r) r=fa[r];
              while (fa[x]!=r) { y=fa[x],fa[x]=r,x=y;}
              return r;
          }
          void unionset(int x,int y){       // x,y roots
               if (rank[x]>rank[y]) fa[y]=x;
               else { fa[x]=y; if (rank[x]==rank[y]) ++rank[y]; }
          }
};
int n , m;
const int N = 20000;
LL a[N] , sumx[N];
void solve(){
    ufset::init();
    for (int i = 0 ; i < n ; ++i){
        scanf("%I64d",&a[i]);
    }
    int x , y;
    while (m --){
        scanf("%d%d",&x,&y);
        if (x>y) swap(x,y);
        if (ufset::find(x) != ufset::find(y))
            ufset::unionset(ufset::find(x) , ufset::find(y));
    }
    memset(sumx , 0 , sizeof(sumx));
    for (int i = 0 ; i < n ; ++i){
        int rot = ufset::find(i);
        sumx[rot] = sumx[rot] + a[i];
    }
    for (int i = 0 ; i < n ;++i){
        if (sumx[ufset::find(i)] < 0){
            puts("IMPOSSIBLE");
            return;
        }
    }
    puts("POSSIBLE");


}
int main(){
    while (cin >> n >> m) solve();
}

C

完全看不懂题意也暂时不会的状压DP


D

一开始写二分,以后一看这种10^18的二分就不用写了嘛!!!

推了将近一个小时公式,心不静总是搞错。后来瞄了一眼老婆的公式,发现一个加号写挫了,就过了。

f: 代表降雨量

double L , K , T1 , T2 , H ;
const double eps = 1e-10;
int dblcmp(double d){
    if (fabs(d)<eps) return 0;
    return d < 0 ? -1 : 1;
}
double gao(double f){
    double speed = f / T1;
    if (dblcmp(f - L) <= 0 ) return f;
    double TT = L / speed;
    double now = L + max<double>(0.0 , speed - K) * (T1 - TT);
    now -= T2 * K;
    now = max<double>(L , now);
    return now;
}
void solve(){
    if (dblcmp(L - H) >0){
        printf("%.9f %.9f\n", H , H);
        return ;
    }
    double temp = K * ( T1 + T2 )  + H;
    double deta = sqrt(temp * temp - 4.0 * L * T1 * K);
    double f2 = -(-deta - temp) / 2.0;
    if (dblcmp(L - H) == 0){
        //f1 = fmax(H , f1);
        //f2 = fmax(H , f2);
        //if (dblcmp(f1 - f2) > 0) swap(f1 , f2);
        printf("%.9f %.9f\n", H , f2);
        return ;
    }
    //if (dblcmp(f1 - f2) > 0) swap(f1 , f2);
    //if (dblcmp(f1 - H) < 0)
        printf("%.9f %.9f\n", f2 , f2);
    //else
        //printf("%.10f %.10f\n", f1 , f2);
        return ;
}
int main(){
    while (~scanf("%lf%lf%lf%lf%lf",&L,&K,&T1,&T2,&H)) solve();
}

G

老婆搞的TreeDp。老婆的TreeDp水平远在屌丝之上啊。用老婆的 —— 求直径的TreeDp模板,然后枚举边,计算最长边,计数。

const int N = 3000;
pair<int , int> res1 , res2;
int dw1[N]; //向下最大
int dw2[N]; //向下次大
int up[N]; //向上最大
int n, mm;
vector<pair<int, int> >v[N];

void dfs1(int s, int pre) //向下最大和向下次大
{
    dw1[s] = dw2[s] = 0;
    int i, ss, dd;
    for(i=0; i<v[s].size(); i++)
    {
        if (v[s][i].second == -1) continue;
        ss = v[s][i].first;
        if (ss == pre) continue;
        dfs1(ss , s);
        dd = v[s][i].second+dw1[ss];
        if(dd >= dw1[s])
        {
            dw2[s] = dw1[s];
            dw1[s] = dd;
        }
        else dw2[s] = max(dw2[s], dd);
    }
}

void dfs2(int s, int pre, int len) //向上最大
{
    int i, ss, dd;
    if(dw1[pre]==dw1[s]+len) up[s] = len + max(up[pre], dw2[pre]);
    else up[s] = len + max(up[pre], dw1[pre]);

    for(i=0; i<v[s].size(); i++)
    {
        if (v[s][i].second == -1) continue;
        ss = v[s][i].first;
        if(ss == pre) continue;
        dd = v[s][i].second;
        dfs2(ss, s, dd);
    }

}

int ansmax;
void dfs3(int s , int pre , int now){
    ansmax = max(ansmax , max(up[s] , dw1[s]));
    if (now == 0){
        int temp = max(up[s] , dw1[s]);
        if (temp < res1.second){
            res1.second = temp;
            res1.first = s;
        }
    }
    else{
        int temp = max(up[s] , dw1[s]);
        if (temp < res2.second){
            res2.second = temp;
            res2.first = s;
        }
    }
    for (int i = 0 ; i < v[s].size(); ++ i){
        if (v[s][i].second == -1 || v[s][i].first == pre) continue;
        dfs3(v[s][i].first , s , now);
    }
}

vector< pair<int , int> > edge;
void solve(){
    for(int i=1; i<=n; i++) v[i].clear();
    edge.clear();
    int ans = 500000;
    int ansi , ansl , ansr;
    int a, b;
    for(int i=2; i<=n; i++)
    {

        scanf("%d%d", &a, &b);
        v[a].push_back( make_pair(b, 1) );
        v[b].push_back( make_pair(a, 1) );
        edge.push_back( make_pair(a,b) );
    }
    for (int i = 0 ; i < n - 1 ; ++i){
        a = edge[i].first;
        b = edge[i].second;
        for (int j = 0 ; j < v[a].size(); ++j)
            if(v[a][j].first == b){
                v[a][j].second = -1;
                break;
            }
        for (int j = 0 ; j < v[b].size(); ++j)
            if (v[b][j].first == a){
                v[b][j].second = -1;
                break;
            }
        dfs1(a , 0);
        dfs2(a, 0, 0);
        dfs1(b , 0);
        dfs2(b , 0, 0);
        ansmax = 0;
        res1.second = 500000;
        dfs3(a , 0 , 0);
        res2.second = 500000;
        dfs3(b , 0 , 1);

//cout<<' '<<i<<' '<<a<<' '<<b<<' '<<res1.second<<' '<<res2.second<<' '<<ans<<endl;
        int zhuzhuzhu = max(res1.second + res2.second + 1 , ansmax);
        if (zhuzhuzhu< ans){
            ans = zhuzhuzhu;
            ansi = i;
            ansl = res1.first;
            ansr = res2.first;
        }



        a = edge[i].first;
        b = edge[i].second;
        for (int j = 0 ; j < v[a].size(); ++j)
            if(v[a][j].first == b){
                v[a][j].second = 1;
                break;
            }
        for (int j = 0 ; j < v[b].size(); ++j)
            if (v[b][j].first == a){
                v[b][j].second = 1;
                break;
            }
    }
    printf("%d\n",ans);
    printf("%d %d\n%d %d\n",edge[ansi].first,edge[ansi].second , ansl ,ansr);
}
int main()
{
    while(~scanf("%d", &n)) solve();
	return 0;
}

好恶心的模拟,有点儿像C2的题目

struct Meng{
    int x , y;
    Meng(){}
    Meng(int _x , int _y):x(_x) , y(_y) {}
    void next(){
        y ++;
        if (y >=5){
            y = 0;
            x ++;
        }
        //return ret;
    }
};
map<char , Meng> Zhu;
const int N = 2000;
char str[N] , s[N];
char mengzhu[5][5];
void output(char x , char y){
    Meng A = Zhu[x];
    Meng B = Zhu[y];
    if (A.x == B.x){
        A.y = (A.y + 1) % 5;
        B.y = (B.y + 1) % 5;
    }
    else if (A.y == B.y){
        A.x = (A.x + 1) % 5;
        B.x = (B.x + 1) % 5;
    }
    else{
        int p = A.x + B.x;
        int q = A.y + B.y;
        A.y = q - A.y;
        B.y = q - B.y;
    }
    printf("%c%c",mengzhu[A.x][A.y] - 'a' + 'A' , mengzhu[B.x][B.y] - 'a' + 'A');
}
void solve(){
    Zhu.clear();
    Meng now = Meng(0,0);
    for (int i = 0 ; i < strlen(s) ; ++i){
        if (s[i] == ' ' || Zhu.find(s[i]) != Zhu.end()) continue;
        mengzhu[now.x][now.y] = s[i];
        Zhu[s[i]] = now;
        now.next();
    }
    for (char i = 'a' ; i <= 'z' ; ++i){
        if (Zhu.find(i) != Zhu.end() || i == 'q') continue;
        mengzhu[now.x][now.y] = i;
        Zhu[i] = now;
        now.next();
    }/*
    for (int i = 0 ; i < 5 ; ++i){
        for (int j = 0 ; j < 5 ;++j)
            printf("%c",mengzhu[i][j]);
        printf("\n");
    }*/
    gets(str);
    int len = 0 , templen = strlen(str);
    for (int i = 0 ; i < templen ; ++i){
        if (str[i] != ' ')
            str[len++] = str[i];
    }
    for (int i = 0 ; i + 1 < len ; i += 2){
        if (str[i] == str[i + 1]){
            for (int j = len ; j > i + 1; --j)
                str[j] = str[j - 1];
            str[i + 1] = 'x';
            len ++;
        }
    }
    if (len & 1) str[len ++ ] ='x';
    for (int i = 0 ; i < len ; i += 2){
        output(str[i] , str[i + 1]);
    }
    printf("\n");

}
int main(){
    while( gets(s) ) solve();

}




总结

1、心不静的时候推公式这件事情很可怕,总是返工;

  2、看见n<=16 第一就应该想到状压DP,并且敢写

  3、读题是硬伤 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值