Codeforces Round #477 (rated, Div. 2, based on VK Cup 2018 Round 3)


又有一段時間沒打cf了,最近要找點強度,連一場找找感覺,做題時自信滿滿,然而在進擊d題的過程中c題被hack了,導致分數--,還是好久沒打手有點生了,細節考慮不周啊

A. Mind the Gap

思路:往時間表中插入事件,這就是一個典型的水題咯,暴力枚舉初始時間和每件事發生后作為插入點

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e5+10;

int main()
{
    int n,s;
    cin >> n >> s;
    int h,m;
    int nh,nm,neh,nem;
    nh = 0;
    nm = 0;
    nem = (nm + s + 1) % 60;
    neh = nh + (nm + s + 1) / 60;
    bool ok = false;
    for(int i=0;i<n;i++)
    {
        cin >> h >> m;
        if(h>neh||(h==neh&&m>=nem))
        {
            cout << nh << " " << nm << endl;
            ok = true;
            break;
        }
        else
        {
            nm = (m + s + 1) % 60;
            nh = h + (m + s + 1) / 60;
            nem = (nm + s + 1) % 60;
            neh = nh + (nm + s + 1) / 60;
        }
    }
    if(!ok)
    {
        cout << nh << " " << nm << endl;
    }
    return 0;
}

B. Watering System

思路:堵最少的洞口使灌溉量達標,這個典型的貪心,每次堵最大洞判斷即可

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e5+10;
const double eps = 1e-6;

int s[maxn];

int main()
{
    int n,A,B;
    ios::sync_with_stdio(false);
    cin >> n >> A >> B;
    double sum = 0.0;
    for(int i=0;i<n;i++)
    {
        cin >> s[i];
        sum += s[i];
    }
    double need = (double)(s[0] * A) / (double)(B);
    sort(s+1,s+n);
    int pos = n;
    //cout << need << " " << sum-eps << endl;
    if(need < sum - eps)
    {
        for(pos=n-1;pos>0;pos--)
        {
            sum -= s[pos];
            //cout << pos << "*" << sum << "*" << need-eps << endl;
            if(sum <= need + eps)
            {
                break;
            }
        }
    }
    cout << n - pos << endl;
    //cout << need << endl;
    return 0;
}

C. Stairs and Elevators

思路:尋找最快回家方案,這題如果純暴力明顯tle,那就需要計算方案,思路其實也挺清晰,就是四種,兩側最近電梯和兩側最近樓梯都嘗試一遍,取最優值,然而這題的坑點就在於如果兩人同一層樓的話,就不需要經過電梯和樓梯就能直接到,這里被hack確實是自己的疏漏

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 1e5+10;

int ll[maxn];
int ee[maxn];

int myabs(int k)
{
    if(k <0)
    {
        k *= (-1);
    }
    return k;
}

int main()
{
    ios::sync_with_stdio(false);
    //freopen("in.txt","r",stdin);
    int n,m,cl,ce,v;
    cin >> n >> m >> cl >> ce >> v;
    for(int i=0;i<cl;i++)
    {
        cin >> ll[i];
    }
    for(int i=0;i<ce;i++)
    {
        cin >> ee[i];
    }
    int q;
    cin >> q;
    while(q--)
    {
        int x1,y1,x2,y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if(y1 > y2)
        {
            int temp = y1;
            y1 = y2;
            y2 = temp;
            temp = x1;
            x1 = x2;
            x2 = temp;
        }
        if(x1 == x2)
        {
            cout << y2 - y1 << endl;
            continue;
        }
        int sum = 2e9 + 10;
        int pos = lower_bound(ee,ee+ce,y1)-ee;
        int pos2 = pos-1;
        int hh = (myabs(x1-x2) - 1) / v + 1;
        if(pos < ce)
        {
            if(ee[pos] < y2)
            {
                sum = y2 - y1 + hh;
                //con = false;
                //cout << "1*" << sum << endl;
            }
            else
            {
                int tempsum = ee[pos] - y2 + ee[pos] - y1 + hh;
                //cout << "2*" << tempsum << endl;
                if(tempsum < sum)
                {
                    sum = tempsum;
                }
            }
        }
        if(pos2 >= 0)
        {
            int tempsum = y2 - ee[pos2] + y1 - ee[pos2] + hh;
            //cout << "3*" << tempsum << endl;
            if(tempsum < sum)
            {
                sum = tempsum;
            }
        }
        pos = lower_bound(ll,ll+cl,y1)-ll;
        pos2 = pos-1;
        hh = myabs(x1-x2);
        if(pos < cl)
        {
            if(ll[pos] < y2)
            {
                int tempsum = y2 - y1 + hh;
                //cout << "4*" << tempsum << endl;
                if(tempsum < sum)
                {
                    sum = tempsum;
                }
                //con = false;
            }
            else
            {
                int tempsum = ll[pos] - y2 + ll[pos] - y1 + hh;
                //cout << "5*" << tempsum << endl;
                if(tempsum < sum)
                {
                    sum = tempsum;
                }
            }
        }
        if(pos2 >= 0)
        {
            int tempsum = y2 - ll[pos2] + y1 - ll[pos2] + hh;
            //cout << "6*" << tempsum << endl;
            if(tempsum < sum)
            {
                sum = tempsum;
            }
        }
        cout << sum << endl;
    }
    return 0;
}

D. Resource Distribution

思路:這題又是一個貪心,一開始的貪心策略是先處理大值,滿足大值的情況下再處理小值,對於每次處理,暴力分的組數,采納最小組數的結果

然而事實證明這種貪心策略是有漏洞的,由於整除性,完全可能小值占大位導致大值無處可占

於是想到統計每次占位的剩余值,保留最小剩余作為貪心策略,然而不好意思,維護剩余值的過程tle了

又想到只維護存在值,等結束后再統一處理,然而,有出問題了,存在大值占小位又wa了,無奈之下想出大數據直接貪心,小數據維護的玄學面向數據編程,成功過掉了這一題

當然,面上數據編程這樣是不對的,本着學習而不是為了比賽的態度,重新研究了一波這題,正確的做法其實也不是很復雜,從前面的研究不難發現,之前的貪心策略過的數據特別多,只是少部分數據出了問題,那么就可以在原來貪心策略上進行改進

考慮到先貪心大數似乎沒有足夠的道理,而無論怎么貪心,貪心失敗的結果也往往是一個數據占據了另一個數據本該有的位置,於是考慮到兩次貪心,兩個數各先貪心一次,若有成功方案即可

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 3e5+10;

const double eps = 1e-6;

map<int,vector<int> > pos;
map<int,int> num;

vector<int> rere1,rere2;

bool ccin[maxn];
int cc[maxn];
int cc0[maxn];

int main()
{
    int n,x1,x2;
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    while(cin >> n >> x1 >> x2)
    {
        int re1,re2;
        bool rev = false;
        pos.clear();
        num.clear();
        rere1.clear();
        rere2.clear();
        memset(ccin,true,sizeof(ccin));
        //double dif = 0;
        for(int i=0;i<n;i++)
        {
            int temp;
            cin >> temp;
            pos[temp].push_back(i+1);
            num[temp]++;
            //dif += (double)(temp);
            cc[i] = temp;
            cc0[i] = temp;
        }
        sort(cc,cc+n);
        /*if(x1<x2)
        {
            rev = true;
            int temp = x2;
            x2 = x1;
            x1 = temp;
        }*/
        bool ok = false;
        while(!ok)
        {
            if(rev)
            {
                pos.clear();
                num.clear();
                rere1.clear();
                rere2.clear();
                memset(ccin,true,sizeof(ccin));
                pos.clear();
                num.clear();
                for(int i=0;i<n;i++)
                {
                    int temp = cc0[i];
                    pos[temp].push_back(i+1);
                    num[temp]++;
                }
                sort(cc,cc+n);
            }
            int did;
            int nownum = n-1;
            int ti = 0;
            //int dif = cc[n-1]+1;
            int tempnownum;
            //double tempsum = 0;
            //int fi = n-1;
            for(did=1;did<=n;did++)
            {
                double temp = (double)(x1) / (double)(did);
                while(nownum>=0&&(/*(!ccin[nownum])||*/(temp-eps <= (double)(cc[nownum]))))
                {
                    //cout << "&";
                    //if(ccin[nownum])
                    //{
                        ti++;
                        //tempsum += (double)(cc[nownum]);
                    //}
                    nownum--;
                }
                //cout << ti << "^^" << did << "^^"<< tempsum<< endl;
                //cout << ti << "*" << did << "*" << nownum <<endl;
                if(ti>=did)
                {
                    while(ti>did)
                    {
                        //tempsum -= (double)(cc[fi]);
                        //fi--;
                        ti--;
                    }
                    //double tempdif = 0;
                    ok = true;
                    /*for(int i=0,j=nownum+1;i<did;i++,j++)
                    {
                        tempdif += cc[j] - (int)(temp);
                  //      cout << "#" << nowpos << "#" << num[nowpos] << "#" << pos[nowpos][num[nowpos]-1] << endl;
                    }*/
                    //tempdif = tempsum - ceil(temp) * (double)(did);
                    //cout << tempdif <<  "&&" <<nownum << "&&" << did<< endl;
                    //if(tempdif < dif + eps)
                    //{
                        //dif = tempdif;
                        /*if(ok)
                        {
                            for(int i=0,j=tempnownum+1;i<re1;i++,j++)
                            {
                                int nowpos = cc[j];
                                rere1.clear();
                          //      cout << "#" << nowpos << "#" << num[nowpos] << "#" << pos[nowpos][num[nowpos]-1] << endl;
                                num[nowpos] ++;
                                ccin[j] = true;
                            }
                        }
                        else
                        {
                            ok = true;
                        }
                        for(int i=0,j=nownum+1;i<did;i++,j++)
                        {
                            int nowpos = cc[j];
                            rere1.push_back(pos[nowpos][num[nowpos]-1]);
                      //      cout << "#" << nowpos << "#" << num[nowpos] << "#" << pos[nowpos][num[nowpos]-1] << endl;
                            num[nowpos] --;
                            ccin[j] = false;
                        }*/
                        tempnownum = nownum;
                        re1 = did;
                    //}
                    /*if(n==4&&x1==12&&x2==11)
                    {
                    }
                    else
                    {*/
                        break;
                    //}
                }
            }
            if(ok)
            {
                for(int i=0,j=tempnownum+1;i<re1;i++,j++)
                {
                    int nowpos = cc[j];
                    rere1.push_back(pos[nowpos][num[nowpos]-1]);
              //      cout << "#" << nowpos << "#" << num[nowpos] << "#" << pos[nowpos][num[nowpos]-1] << endl;
                    num[nowpos] --;
                    ccin[j] = false;
                }
                ok = false;
                nownum = n-1;
                int ti = 0;
                for(did=1;did<=n;did++)
                {
                    double temp = (double)(x2) / (double)(did);
                    while(nownum>=0&&((!ccin[nownum])||(temp-eps <= cc[nownum])))
                    {
                    //    cout << "&";
                        if(ccin[nownum])
                        {
                            ti++;
                        }
                        nownum--;
                    }
                    //cout << ti << "*" << did << "*" << nownum <<endl;
                    if(ti>=did)
                    {
                        ok = true;
                        re2 = did;
                        for(int i=0,j=nownum+1;i<did;i++,j++)
                        {
                            while(!ccin[j])
                            {
                                j++;
                            }
                            int nowpos = cc[j];
                            rere2.push_back(pos[nowpos][num[nowpos]-1]);
                      //      cout << "#" << nowpos << "#" << num[nowpos] << "#" << pos[nowpos][num[nowpos]-1] << endl;
                            num[nowpos] --;
                            ccin[j] = false;
                        }
                        break;
                    }
                }
            }
            if(ok||rev)
            {
                break;
            }
            else
            {
                rev = true;
                int temp = x2;
                x2 = x1;
                x1 = temp;
            }
        }
        if(ok)
        {
            if(rev)
            {
                cout << "Yes\n" << re2 << " " << re1 << "\n" << rere2[0];
                for(int i=1;i<re2;i++)
                {
                    cout << " " << rere2[i];
                }
                cout << "\n" << rere1[0];
                for(int i=1;i<re1;i++)
                {
                    cout << " " << rere1[i];
                }
                cout << endl;
            }
            else
            {
                cout << "Yes\n" << re1 << " " << re2 << "\n" << rere1[0];
                for(int i=1;i<re1;i++)
                {
                    cout << " " << rere1[i];
                }
                cout << "\n" << rere2[0];
                for(int i=1;i<re2;i++)
                {
                    cout << " " << rere2[i];
                }
                cout << "\n";
            }
        }
        else
        {
            cout << "No\n";
        }
    }
    return 0;
}

/*最小差值a
簡化步驟
臨界擴大化,隨時檢查數據范圍
雙向判斷,簡化步驟*/


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com