답안 #477385

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
477385 2021-10-02T00:34:45 Z llcd Building Bridges (CEOI17_building) C++17
0 / 100
3 ms 332 KB
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<iomanip>
#define fi first
#define se second
#define forl(i,a,b) for(int i=a;i<=b;i++)
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<ll,ll> ii;
typedef pair<ii,int> iii;
typedef pair<long double,int> ldi;
ll n,h[100005],w[100005],gt[100005];
int sh=0;
//sub2
map<int,ii> line;
ll cal(int num_line,ll x)
{
    return 1LL*line[num_line].first*x + line[num_line].second;
    // tính y=ax+b;
}
ll giao_diem(int nline1,int nline2,bool isright)
{
    ll a=line[nline1].second-line[nline2].second;
    ll b=line[nline2].first-line[nline1].first;
    if(b==0)return 999999999999999;
    if((a%b)==0)return (a)/(b)+1;
    if(isright) return (a)/(b)+1;// a<0
    return (a)/(b)+1;
}
/**/
set<iii> s;// hệ số góc , biên trái, số hiệu
set<ii> s2;// biên trái, số hiệu
bool important(int sh,ll left,set<iii>::iterator it)
{
    if(it==s.begin())return true;
    it--;
    iii num=*it;
    if(left>giao_diem(sh,num.second,0))return false;//ko quan trọng
    return true;
}
void insert_line(ll a,ll b)
{
    sh++;
    line[sh]=ii(a,b);
    set<iii>::iterator it=s.begin();
    ll left=-999999999999999;
    //cout<<"insert y="<<a<<"x + "<<b<<endl;
    while(true)
    {
        if(s.empty())break;
        it = s.lower_bound(iii(ii(a,-999999999999999),-1));
        if(it==s.end()){break;}
        iii num=*it;
        int nline=num.second;
        //cout<<"line:"<<nline<<endl;
        left=giao_diem(sh,nline,0);//giao điểm của đt hiện tại và đt *it
        //cout<<sh<<": left="<<left<<endl;
        //song song
        if(left==999999999999999)
        {
            if(a>0)
            {
                //cout<<"C1"<<endl;
                if(b>line[nline].second){left=num.first.second;s.erase(it);s2.erase(ii(num.first.second,num.second));}
                else return;
            }
            else
            {
                //cout<<"C2"<<endl;
                if(b<line[nline].second){left=num.first.second;s.erase(it);s2.erase(ii(num.first.second,num.second));}
                else return;
            }
        }
        else
        {
            if(!important(sh,left,it)){return;}//cout<<"ko push"<<endl;
            if(left<=num.first.second){left=num.first.second;s.erase(it);s2.erase(ii(num.first.second,num.second));}
            else break;
        }
    }
    //cout<<sh<<" Ok1"<<endl;

    if(s.size()>=1 && it!=s.begin())
    {
        //cout<<"Continue:"<<endl;
        it--;
        iii tam=*it;
        //cout<<"Bỏ đường thẳng số "<<tam.second<<endl;
        s.erase(it);
        s2.erase(ii( tam.first.second, tam.second));
        s.insert(iii( ii(tam.first.first, giao_diem(sh,tam.second,1)) , tam.second));
        s2.insert(ii( giao_diem(sh,tam.second,1) , tam.second ));
    }
    s.insert(iii( ii(a,left),sh));
    s2.insert(ii(left,sh));

    //cout<<"list đoạn thẳng"<<endl;
    //for(auto it:s)cout<<it.first.first<<" "<<it.first.second<<" "<<it.second<<endl;
    //cout<<"end_________________________________________"<<endl;
}
ll query(int x)
{
    set<ii>::iterator it=s2.lower_bound(ii(x,0));
    ii tam=*it;
    ll ans=cal(tam.second,x);
    if(it==s2.begin())return ans;
    it--;
    tam=*it;
    it++;it++;
    ans=min(ans,cal(tam.second,x));
    if(it==s2.end())return ans;
    tam=*it;
    ans=min(ans,cal(tam.second,x));
    return ans;
    //cout<<x<<" -> thuộc đoạn y="<<line[tam.second].first<<"x + "<<line[tam.second].second<<endl;

}

//sub1
ll cost(int from,int to)
{
    return (w[to-1]-w[from]);
}
void sub1()
{
    ll dp[n+5];
    dp[1]=0;
    forl(i,2,n)
    {
        dp[i]=1e15;
        forl(j,1,i-1)
        {
            dp[i]=min(dp[i],dp[j]+(h[i]-h[j])*(h[i]-h[j])+cost(j,i));
           // cout<<i<<" "<<j<<": "<<dp[j]<<" "<<(h[i]-h[j])*(h[i]-h[j])<<" "<<cost(j,i)<<endl;
           // cout<<"-> "<<dp[j]+(h[i]-h[j])*(h[i]-h[j])+cost(j,i)<<endl;
        }
    }
    cout<<dp[n];
    //forl(i,1,n)cout<<dp[i]<<" ";cout<<endl;
}
void sub2()
{
    ll dp[n+5];dp[1]=0;//dp[2]=(h[2]-h[1])*(h[2]-h[1]);
    // chi phí xây từ 1 -> i
    // = (h[i]-h[j])^2 -  w[i] - w[j] + dp[j]
    // = hi^2 - 2*hi*hj + hj^2 - wi - wj +dp[j]
    // = (-2*hj) * hi  + (hj^2-wj+dp[j]) +  hi^2 - wi
    //      a    *  x  +     b           +    CONST
    insert_line( -2*h[1] ,  h[1]*h[1] +dp[1] );
    //cout<<0<<" ";
    forl(i,2,n)
    {
       // cout<<i<<"__________\n ";
        //cout<<i<<": list đoạn thẳng"<<endl;
        //for(auto it:s2){cout<<it.first<<" -> numline="<<it.second<<": ";
        //cout<<line[it.second].first<<"x + "<<line[it.second].second<<endl;}
        //cout<<endl;
        dp[i]=query(h[i]) + h[i]*h[i] - gt[i];
        //cout<<"dp["<<i<<"]= "<<dp[i]+w[i]<<" <>\n";
        insert_line(-2*h[i], h[i]*h[i]+dp[i]);

    }
    cout<<dp[n]+w[n]-gt[1]-gt[n];
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("xaycau.inp","r",stdin);
        freopen("xaycau.out","w",stdout);
    #endif // ONLINE_JUDGE

    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    w[0]=0;
    forl(i,1,n)cin>>h[i];
    forl(i,1,n){cin>>gt[i];if(i==1 || i==n)gt[i]=0;}
    forl(i,1,n){w[i]=w[i-1]+gt[i];}

   // forl(i,1,n)cout<<w[i]<<" ";cout<<endl;
   // cout<<cost(3,5)<<endl;
    if(n<=2000)sub1();else sub2();
    //sub1();cout<<endl;sub2();cout<<endl;

    /*insert_line(0,4);
    insert_line(-3,12);
    insert_line(0,2);
    insert_line(2,1);
    insert_line(-3,2);
    cout<<"list đoạn thẳng"<<endl;
    for(auto it:s2)cout<<it.first<<" "<<it.second<<endl;
    cout<<"QUERY:"<<endl;
    forl(i,-3,5)cout<<i<<": "<<query(i)<<endl;*/
    //cout<<"list đoạn thẳng"<<endl;
    //(auto it:s2)cout<<it.first<<" -> "<<it.second<<endl;
}

Compilation message

building.cpp: In function 'int main()':
building.cpp:174:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  174 |         freopen("xaycau.inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
building.cpp:175:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  175 |         freopen("xaycau.out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 2 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 2 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -