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
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(xint 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(iFOR(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;
}

你可能感兴趣的:(考试总结)