您的位置:首页 > 其它

2017.11.06离线赛总结

2017-11-06 20:51 281 查看

dna ——3811

思路:经过昨天第1题的教育后,今天第1题都虚的一档一档写了,结果在暴力的时间上花的太多了,导致想成纯hash(其实题没审清楚),正解十分从简,因为只有4种字符,k也很小,4进制枚举就行了(T_T)。

seq ——3812

思路:神tm数学题,推导公式。

暴力15分,不解释;

当a0于a1同号时,可推出从s=4开始数列严格单调(题解时这么说的…),所以就暴力求出前几项就行了…

之后的一些小分的数据类同,数列一定会在s=x时严格单调,那么就要去找到这个位置,即单峰。

由于这是一道纯数学题,蒟蒻我不想多说什么了。(题解还说此题已经弱化了,原题是Ax=k1∗Ay+k2∗Ai,x=i+2,y=i+1)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define pb push_back

void Rd(int &x){
x=0;char c;int f=1;
while(c=getchar(),c<48)if(c=='-')f=-1;
do x=(x<<1)+(x<<3)+(c^48);
while(c=getchar(),c>47);
x*=f;
}

#define M 100005
#define N 300005

int n,m;
int s[M];
LL f
;
int a0,a1,k;

struct p15{
void solve(){
f[0]=a0,f[1]=a1;
REP(i,2,s[m])f[i]=1LL*k*f[i-1]+f[i-2];
LL Mx=-INF,Mn=INF;
int Mx_id=s[1],Mn_id=s[1];
REP(i,1,m){
if(f[s[i]]>Mx)Mx_id=s[i],Mx=f[s[i]];
if(f[s[i]]<Mn)Mn_id=s[i],Mn=f[s[i]];
}
printf("%d %d\n",Mx_id,Mn_id);
}
}p15;
//struct p20{
//  void solve(){
//      REP(i,2,10)f[i]=1LL*k*f[i-1]+f[i-2];
//      LL Mx=-INF,Mn=INF;
//      int Mx_id=s[1],Mn_id=s[1];
//      REP(i,1,m){
//          if(s[i]>5)break;
//          if(f[s[i]]>Mx)Mx_id=s[i],Mx=f[s[i]];
//          if(f[s[i]]<Mn)Mn_id=s[i],Mn=f[s[i]];
//      }
//      if(f[8]<0)printf("%d %d\n",Mx_id,s[m]);
//      else printf("%d %d\n",s[m],Mn_id);
//  }
//}p20;
struct p100{
void solve(){
f[0]=a0,f[1]=a1;
int Mx_id=s[1],Mn_id=s[1];
int i;
for(i=2;i<=s[m];i++){
f[i]=1LL*k*f[i-1]+f[i-2];
if(  (f[i-1]>=0) == (f[i]>=0) ){
if(f[i]<0 && min(f[i],f[i-1])<min(f[0],f[1]) )break;
if(f[i]>0 && max(f[i],f[i-1])>max(f[0],f[1]) )break;
}
}
for(int j=2;s[j]<=i && j<=m;j++){
if(f[Mn_id]>f[s[j]])Mn_id=s[j];
if(f[Mx_id]<f[s[j]])Mx_id=s[j];
}
if(i<s[m]){
if(f[i]<0)Mn_id=s[m];
if(f[i]>0)Mx_id=s[m];
}
printf("%d %d\n",Mx_id,Mn_id);
}
}p100;
int main(){
//  freopen("seq.in","r",stdin);
//  freopen("seq.out","w",stdout);
//  printf("%d\n",(Sz(f)+Sz(s))/1024/1024);
cin>>m;
REP(i,1,m)Rd(s[i]);
cin>>n;
REP(i,1,n){
Rd(a0),Rd(a1),Rd(k);
if(!a0 && !a1)printf("%d %d\n",s[1],s[1]);
else if(n<=100 && m<=100 && s[m]<=10)p15.solve();
else p100.solve();
}
return 0;
}


trip ——3812

思路:暴力bfs或dfs随意前枝应该就有50分(数据略弱),考试时也有想到要预处理每次到的状态后的答案——记忆化(75分)->dp。

记忆化这里不多说了,按照dfs的参数x(到的点),y(还剩下的钱),z(还剩下的路程)来定义就行了。

正解dp也显然要预处理,

首先考虑的还是状态,从状态定义入手,处理出i 到j 经过不超过c条路径的最大路程。

这里还需要倍增,因为从i到j的汽油量都是减少1的

也就是从i到j经过不超过2k 条路径的最大路程。

然而这样还不够,最后还要二分答案or查找来优化一个小log卡过…

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define pb push_back

#define N 105
#define M 1005
#define S 100005
#define TM 17

int n,m,C,T;

struct Node{
int p,c;
}A
;
struct edge{
int to,cost;
};
vector<edge>E[M];
struct Ans{
int s,q,d;
}Q[S];

//struct p50{
//  struct node{
//      int x,y,z;
//  };
//  queue<node>G;
//
//  int dis
[M]
;
//  bool mark
[M]
;
//
//    void solve(){
//        REP(i,1,T){
//            int ans=-1;
//            mcl(dis,-1);
//            dis[Q[i].s][Q[i].q][0]=0;
//            G.push((node){Q[i].s,Q[i].q,0});
//
//            while(!G.empty()){
//                int x=G.front().x,y=G.front().y,z=G.front().z;
//                G.pop();
//                mark[x][y][z]=0;
//                if(dis[x][y][z]>=Q[i].d){ans=max(ans,y);continue;}
//                if(y<=ans)continue;
//                if(z){
//                    REP(j,0,E[x].size()-1){
//                        int to=E[x][j].to,cost=E[x][j].cost;
//                        if (dis[to][y][z-1]<dis[x][y][z]+cost){
//                            dis[to][y][z-1]=dis[x][y][z]+cost;
//                            if (!mark[to][y][z-1]){
//                                mark[to][y][z-1]=1;
//                                G.push((node){to,y,z-1});
//                            }
//                        }
//                    }
//                }
//                if (z<A[x].c && y>=A[x].p){
//                    if (dis[x][y-A[x].p][A[x].c]<dis[x][y][z]){
//                        dis[x][y-A[x].p][A[x].c]=dis[x][y][z];
//                        if (!mark[x][y-A[x].p][A[x].c]){
//                            mark[x][y-A[x].p][A[x].c]=1;
//                            G.push((node){x,y-A[x].p,A[x].c});
//                        }
//                    }
//                }
//            }
//            printf("%d\n",ans);
//        }
//    }
//}p50;
//struct p75{
//    LL dp
[570][M];
//    LL dfs(int x,LL money,int res){
//        LL &t=dp[x][money][res];
//        if(t!=-1)return t;
//        t=0;
//        REP(i,0,E[x].size()-1){
//            edge y=E[x][i];
//            if(money>=A[x].p&&res<A[x].c)t=max(t,dfs(y.to,money-A[x].p,A[x].c-1)+y.cost);
//            if(res)t=max(t,dfs(y.to,money,res-1)+y.cost);
//        }
//        return t;
//    }
//    void solve(){
//        memset(dp,-1,sizeof(dp));
//        REP(j,1,T){
//            int ans=-1;
//            REP(i,0,Q[j].q){
//                LL res=dfs(Q[j].s,i,0);
//                if(res>=Q[j].d){
//                    ans=Q[j].q-i;
//                    break;
//                }
//            }
//            printf("%d\n",ans);
//        }
//    }
//}p75;
int dp
[N*N],f

[TM],w

,tmp
;
struct p100{
void Init(){
mcl(w,192);
REP(i,1,n)w[i][i]=0;
REP(l,1,TM-1)
REP(i,1,n)
REP(j,1,n){
f[i][j][l]=f[i][j][l-1];
REP(k,1,n)f[i][j][l]=max(f[i][j][l],f[i][k][l-1]+f[k][j][l-1]);
}
REP(l,0,TM-1){
REP(i,1,n){
if(!((1<<l)&A[i].c))continue;
mcl(tmp,192);
REP(j,1,n)REP(k,1,n)tmp[j]=max(tmp[j],w[i][k]+f[k][j][l]);
REP(j,1,n)w[i][j]=max(w[i][j],tmp[j]);
}
}
mcl(dp,192);
REP(i,0,n*n)
REP(j,1,n){
if (i<A[j].p){dp[j][i]=0;continue;}
REP(k,1,n)dp[j][i]=max(dp[j][i],w[j][k]+dp[k][i-A[j].p]);
}
}
void solve(){
mcl(dp,-1);
Init();
REP(i,1,T){
int L=0,R=Q[i].q,used=Q[i].q+1;
while(L<=R){
int mid=(L+R)>>1;
if(dp[Q[i].s][mid]>=Q[i].d)used=mid,R=mid-1;
else L=mid+1;
}
printf("%d\n",Q[i].q-used);
}
}
}p100;
int main(){
//      freopen("trip.in","r",stdin);
//      freopen("trip.out","w",stdout);
cin>>n>>m>>C>>T;
REP(i,1,n){
scanf("%d%d",&A[i].p,&A[i].c);
A[i].c=min(A[i].c,C);
}
mcl(f,192);
REP(i,1,m){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
E[x].pb((edge){y,z});
f[x][y][0]=max(f[x][y][0],z);
}
REP(i,1,T)scanf("%d%d%d",&Q[i].s,&Q[i].q,&Q[i].d);
//      p50.solve();
//      p75.solve();
p100.solve();
return 0;
}


小结:今天考得不好,讲道理应该有165,结果比暴力的分(150)还少(130分)…可能还是第1题的策略没搞好,而且第2题迷之爆零(切分太乱了,错的也切进去了,又因为是多测试数据,结果应该是一个测试点挂了)。

这说明我的策略还是不够到位,时间分配还不是很合理,审题的能力还不行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: