查看: 1377|回復: 1
打印 上一主題 下一主題

[TIOJ] 1225 - 數字合併

[複製鏈接]
  • TA的每日心情
    開心
    2015-4-12 10:09
  • 簽到天數: 137 天

    [LV.7]常住居民III

    142

    主題

    686

    帖子

    3559

    積分

    邁向天堂

    蘇多門

    Rank: 8Rank: 8

    積分
    3559

    新手達陣台南一中資訊社程式設計達人 - 2014

    跳轉到指定樓層
    樓主
    發表於 2014-10-25 17:55:54 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

    趕快加入我們來參與討論吧!

    您需要 登錄 才可以下載或查看,沒有帳號?加入我們

    x
    http://tioj.ck.tp.edu.tw/problems/1225

    用stack做,保持stack裡面是遞減的狀態,O(n)

    [C++] 純文本查看 復制代碼
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	long long ans=0; 
    	vector<int> stk;
    	stk.reserve(n);
    	for(int i=0;i<n;i++)
    	{
    		int now;
    		scanf("%d",&now);
    		while(stk.size()>0 && now>=stk.back())
    		{
    			stk.pop_back();
    			if(!stk.empty())
    				ans+=min(stk.back(),now);
    			else
    				ans+=now;
    		}
    		stk.push_back(now);
    	}
    	for(int i=0;i<stk.size()-1;i++)
    		ans+=stk[i];
    	printf("%lld\n",ans);
    }
    


    我第一次的做法:
    用divide and conquer遞迴下去,但最壞狀況(遞減數列)會是O(n^2),所以TLE
    [C++] 純文本查看 復制代碼
    #include<cstdio>
    using namespace std;
    int n;
    int a[1000010];
    long long sol(int s,int e,int b)
    {
    	if(s==e+1)
    		return 0;
    	if(s==e)
    		return b;
    	int m=s;
    	for(int i=s;i<=e;i++)
    		if(a[i]>a[m])
    			m=i;
    	return sol(s,m-1,a[m])+sol(m+1,e,a[m])+b;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=0;i<n;i++)
    		scanf("%d",&a[i]);
    	printf("%lld\n",sol(0,n-1,0));
    }
    
    蘇多門 domen111
    My Web: https://sites.google.com/site/domenprg/
    回復

    使用道具 檢舉

  • TA的每日心情
    慵懶
    2015-4-10 14:18
  • 簽到天數: 78 天

    [LV.6]常住居民II

    176

    主題

    612

    帖子

    3959

    積分

    管理員

    Rank: 9Rank: 9Rank: 9

    積分
    3959

    台南一中資訊社新手達陣程式設計達人 - 2014

    頭香
    發表於 2014-10-25 23:24:13 | 只看該作者
    針對Divide and Conquer 的補救作法,利用線段數來避免最壞狀況

    隨機狀況:[tex]O(nlogn+log^4n)[/tex]
    遞增減或交錯:[tex]O(nlogn+nlogn)[/tex]

    [C++] 純文本查看 復制代碼
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int in[1000000];
    int N;
    
    typedef long long ll;
    typedef pair<int,int> pll;
    pll sq[2200000];
    void modify(int i,int v,int L,int R,int id)
    {
    	if(L==R){
    		sq[id]={v,i};
    		return ;
    	}
    	int M = (L+R)/2;
    	if(i<=M)modify(i,v,L,M,id*2);
    	else modify(i,v,M+1,R,id*2+1);
    	sq[id] = max(sq[id*2],sq[id*2+1]);
    }
    pll max(int l,int r,int L,int R,int id)
    {
    	if(l<=L&&R<=r)
    		return sq[id];
    	if(r<L||R<l)
    		return {0,0};
    	int M = (L+R)/2;
    	return max( max(l,r,L,M,id*2),max(l,r,M+1,R,id*2+1) );
    }
    #define rmq 0,N-1,1
    ll solve(int L,int R)
    {
    	if(L==R)return 0;
    	if(L+1==R){
    		return max(in[L],in[R]);
    	}
    	ll cost = 0;
    	pll mv = max(L,R,rmq);
    	ll mid = mv.second;
    	ll val = mv.first;
    	if( L < mid )
    	{
    		cost+=solve(L,mid-1);
    		cost+=val;
    	}
    	if( mid < R )
    	{
    		cost+=solve(mid+1,R);
    		cost+=val;
    	}
    	return cost;
    }
    int main()
    {
    	ll sum=0;
    	bool inc = true;
    	bool dec = true;
    	scanf("%d",&N);
    	for(int i=0;i<N;++i)
    	{
    		scanf("%d",&in[i]);
    		modify(i,in[i],rmq);
    		sum+=in[i];
    		if(i){
    			if(in[i-1]<in[i])dec=false;
    			if(in[i-1]>in[i])inc=false;
    		}
    	}
    	if(!inc && !dec)
    		printf("%lld\n",solve(0,N-1));
    	else
    		printf("%lld\n",sum-*min_element(in,in+N));
    }
    回復 支持 反對

    使用道具 檢舉

    您需要登錄後才可以回帖 登入 | 加入我們

    本版積分規則

    快速回覆 返回頂部 返回列表