2017-11-6離線賽總結(NOIP七連測第四場)

失分小結:
估分:155 100+20+35
實際分數:140 100+20+20
考完太突然發現第二題的正經切分的運算被刪掉了,實際的20分是玄學解法幫我水的…
第三題由於造數據太煩,就沒有怎麼去管他,然後dp順序的錯誤導致又失去15分
本來的考試note上寫的預估分數是100+30+50,後來感覺第二題只有20分不太好,就放棄寫第三題下面15分,回過頭去寫第二題
但又因爲第二題 複雜度玄學+好像會超long long+不想打高精+判斷好煩
就直接判此玄學解法爲錯誤解法…然後盯着三份代碼發呆半小時

其實考試難歸難,可以發現隔壁機房的學長大部分的也在100+,只不過他們的分數會比我都高上三四十分 其實如果完全按照note打,也照樣可以寫到那麼多分
而且特別忌諱邊寫邊調,第二題就是硬生生調了半個小時,過不了大樣例,就放棄了敲到一半的正解

還有就是要建立代碼自信,看到一道題,要進過嚴密的分析後再動手,即使他沒有使用什麼算法,有時也是可解的
雖然說今天的第二題略爲玄學,但第三題還是很符合NOIP的難度的,各種優化dp,也沒有超出考試的範圍

距離NOIP還有4天,fighting!

題解:
1.DNA序列
考察Hash,看到數據範圍知道是線性判斷,然後直接哈Hash就好
2.數列遞推
乍一眼看覺得是數學題,總要求一下通項公式吧…
在求不出通項公式後,看了一下大數據的輸出,發現總有一個值爲S[m]
然後再結合切分,分析出了單調性,當兩數符號相同時,接下來的數字是單調增(減)的
在此之前,爲一個擺動函數,在看題解前,感覺這個擺動次數簡直玄學,怎麼都不認爲這樣可以過,還有對於S的判斷,S的範圍可能不超過序列的擺動範圍,所以需要一系列特判代碼功底還是太弱了
3.旅遊路線
這算是一道可被轉移到線性dp的題目
題目的維度很多:
1.地點
2.油量
3.錢數
4.路程
進過分析可以發現 錢數或路程可被作爲dp對應的值
然後直接根據題意模擬即可水到50
使用暴搜的只要套上記憶化就可以水到60(聽說多的有75)【數組要開得夠大】
然後考慮優化空間
可以發現,油量與加油的地點的關係並不大,加油站是幫你把它的油量加到ci
所以只要保證能用當前油量行駛到加油站就好
然後我們可以預處理在i點加油,行駛到j點的最大路程
再在dp裏引用,這樣dp轉移是n^4的【dp含義爲從i出發花費j元的最遠行駛路程】
在詢問時直接詢問從i點出發,花費j元的最遠行駛路程就好了
這樣複雜度爲O(Cnm+n4+Tn2) 可以水到75分【可見預處理的魅力】
然後看到線性單調取值,聯想到倍增優化,倍增優化預處理
複雜度縮爲O(nmlogC+n4+Tn2) 這樣就有95分了
然後可以發現最後的枚舉可以優化爲二分
複雜度再次優化爲O(nmlogC+n4Tlog(n2)) 拿到滿分…
代碼實現:

#include<bits/stdc++.h>
using namespace std;

#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 105
#define S 21

void Rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>=48);
}

inline void chk_mx(int &x,int y){if(x<y)x=y;}

int Mx[S][N][N],len[S][N][N],dp[N*N][N]; 
int pi[N],ci[N];

int main(){
    int n,m,C,T;
    scanf("%d%d%d%d",&n,&m,&C,&T);

    memset(len,192,sizeof len);
    memset(Mx,192,sizeof Mx);

    FOR(i,1,n)Rd(pi[i]),Rd(ci[i]),ci[i]=min(ci[i],C);
    FOR(i,1,m){
        int a,b,c;
        Rd(a),Rd(b),Rd(c);
        Mx[0][a][b]=c;
    }
    FOR(i,1,n)len[0][i][i]=0;

    FOR(i,1,S-1)FOR(j,1,n)FOR(k,1,n){
        chk_mx(Mx[i][j][k],Mx[i-1][j][k]);
        FOR(ii,1,n)chk_mx(Mx[i][j][k],Mx[i-1][j][ii]+Mx[i-1][ii][k]);
    }
    FOR(i,1,S-1)FOR(j,1,n)FOR(k,1,n){
        chk_mx(len[i][j][k],len[i-1][j][k]);
        if(ci[j]&(1<<(i-1)))FOR(ii,1,n)chk_mx(len[i][j][k],len[i-1][j][ii]+Mx[i-1][ii][k]);
    } 

    FOR(i,0,n*n)FOR(j,1,n){
        if(i<pi[j])continue;
        FOR(k,1,n)chk_mx(dp[i][j],dp[i-pi[j]][k]+len[20][j][k]);
    }

    while(T--){
        int sta,mon,dis;
        Rd(sta),Rd(mon),Rd(dis);
        int l=0,r=mon,res=mon+1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(dp[mid][sta]>=dis){
                r=mid-1;
                res=mid;
            }
            else l=mid+1;
        }
        printf("%d\n",mon-res);
    }   
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章