JSZX Winter Camp Day 3 爆零记

Posted fish-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSZX Winter Camp Day 3 爆零记相关的知识,希望对你有一定的参考价值。

JSZX Winter Camp Day 3 爆零记

emmmm蒟蒻的我爆零啦!!T1码了个dijikstra然后T了,正解为Floyd。T2蒟蒻并不会,唯一会的只有暴力。。T3写了个Trie然后MLE了,然而正解是

哈希。T4是蒟蒻唯一一道会的,然而却忘了开long long。手动GG。。

<T1>

题意:在一个有向图中,求从指定起点到指定终点的最小值,最小值定义为路径上的边权和减去路径上点权的最小值。

超时代码:

技术分享图片
#include<cstdio>
#include<algorithm>
#define maxn 300
#define inf 2e9
using namespace std;
int vis[maxn],head[maxn],tot,n,m,w[maxn];
struct DIS{
    int juli,minn;
}dis[maxn];
int read(){
    int w=0,f=1;char c=getchar();
    while(c<0||c>9) if(c==-) f=-1,c=getchar();
    while(c>=0&&c<=9) w=w*10+c-48,c=getchar();;
    return w*f;
}
struct Edge{
    int to,next,v;
}e[200050];
void add(int x,int y,int v){
    e[++tot]=(Edge){y,head[x],v};head[x]=tot;
}
void dijk(int s){
    int i,j;
    for(i=1;i<=n;i++) if(w[i]==-1) vis[i]=true;
//    printf("w:%d vis:%d\n",w[2],vis[2]);
    for( i=head[s];i;i=e[i].next){
        if(!vis[e[i].to]) dis[e[i].to].juli=e[i].v-min(w[e[i].to],w[s]),dis[e[i].to].minn=min(w[e[i].to],w[s]);
    }
    for(i=1;i<=n;i++){
        int mi=inf,k;
        for(j=1;j<=n;j++){
            if(!vis[j]&&dis[j].juli<mi) mi=dis[j].juli,k=j;
        }
//        printf("k:%d   vis[2]:%d\n",k,vis[2]);
        vis[k]=true;
        for(j=head[k];j;j=e[j].next){
            if(!vis[e[j].to]&&(mi+e[j].v-min(w[e[j].to],dis[e[j].to].minn)+dis[e[j].to].minn)<dis[e[j].to].juli)
            dis[e[j].to].juli=mi+e[j].v-min(w[e[j].to],dis[e[j].to].minn)+dis[e[j].to].minn,dis[e[j].to].minn=min(dis[e[j].to].minn,w[e[j].to]);
        }
        
    }
}
int main(){
    freopen("T1_.in","r",stdin);
    freopen("T1_.out","w",stdout);
int i,x,y,v,q,s,t;
    n=read();m=read();
    for(i=1;i<=n;i++){
        w[i]=read();
    }
    for(i=1;i<=m;i++){
        x=read();y=read();v=read();
        add(x,y,v);add(y,x,v);
    }
    q=read();
    while(q--){
        s=read();t=read();
        if(w[s]==-1||w[t]==-1){
            printf("mon panache!\n");continue;
        }
        for(i=1;i<=n;i++) dis[i].juli=inf;
//        printf("1");
        for(i=1;i<=n;i++) vis[i]=false;
        dijk(s);
        if(dis[t].juli==inf) printf("mon panache!\n");
        else printf("%d\n",dis[t]);
//        printf("1");
    }
    return 0;
}
T1

正解(某大神):

技术分享图片
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=233+23;
struct zs{int v,id;}a[maxn];
ll dis[maxn][maxn],ans[maxn][maxn];
int id[maxn];
int i,j,k,n,m;


int ra,fh;char rx;
inline int read(){
    rx=getchar(),ra=0,fh=1;
    while(rx<0)rx==-&&(fh=-1),rx=getchar();
    while(rx>=0)ra=ra*10+rx-48,rx=getchar();return ra*fh;
}

inline ll min(ll a,ll b){return a<b?a:b;}
bool operator <(zs a,zs b){return a.v<b.v;}
int main(){
    freopen("T1_.in","r",stdin);
    freopen("T1_.out","w",stdout);
    n=read(),m=read();
    for(i=1;i<=n;i++)a[i].v=read(),a[i].id=i;
    sort(a+1,a+1+n);
    for(i=1;i<=n;i++)id[a[i].id]=i;
    
    memset(dis,10,sizeof(dis)),memset(ans,10,sizeof(ans));;
    for(i=1;i<=m;i++)j=id[read()],k=id[read()],dis[k][j]=dis[j][k]=min(dis[j][k],read());
    
    for(k=n;k;k--)if(a[k].v>-1)
        for(i=1;i<=n;i++)for(j=1;j<=n;j++)
            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]),
            ans[i][j]=min(ans[i][j],dis[i][j]-a[k].v);
    int q=read();
    while(q--){
        i=id[read()],j=id[read()];
        if(ans[i][j]<=1e17)printf("%lld\n",ans[i][j]);else puts("mon panache!");
    }
}
T1

<T2>

题意:求I字形的最大面积,规定I字形,分为三个矩形,第二个矩形一定比另外两个窄。

技术分享图片
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=205;
const int inf=1002333;
int f[2][3][maxn][maxn];
int sm[maxn][maxn],mx1[maxn][maxn],mx2[maxn][maxn];
int n,m,pre,now,ans,tmpmx;
 
int ra;char rx;
inline int read(){
    rx=getchar(),ra=0;
    while(rx<0||rx>9)rx=getchar();
    while(rx>=0&&rx<=9)ra*=10,ra+=rx-48,rx=getchar();return ra;
}
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
char rs[233];
int main(){
    freopen("T6_.in","r",stdin);
    freopen("T6_.out","w",stdout);
    register int i,j,k;
    n=read(),m=read();
    for(i=1;i<=n;i++){
        scanf("%s",rs+1);
        for(j=1;j<=m;j++)sm[i][j]=sm[i][j-1]+(rs[j]==1);
    }
    for(i=1;i<=m;i++)sm[0][i]=i;
     
    now=1,pre=0;
    for(i=1;i<=2;i++)memset(f[0][i],200,sizeof(f[0][i]));
    for(i=1;i<=n;i++,swap(now,pre)){
        for(j=1;j<m;j++)for(k=j+1;k<=m;k++)
            if(sm[i][k]==sm[i][j-1])
                f[now][0][j][k]=(sm[i-1][k]==sm[i-1][j-1]?f[pre][0][j][k]:0)+k-j+1;
            else f[now][0][j][k]=-inf;
         
         
        for(j=1;j<m;j++)for(k=m,tmpmx=-inf;k>j;k--)
            tmpmx=max(tmpmx,f[pre][0][j][k]),
            mx1[j][k]=max(mx1[j-1][k],tmpmx);
        for(j=2;j<m;j++)for(k=j;k<m;k++)
            if(sm[i][k]==sm[i][j-1]){
                f[now][1][j][k]=f[pre][1][j][k]+k-j+1;
                if(sm[i-1][k+1]==sm[i-1][j-2])
                    f[now][1][j][k]=max(f[now][1][j][k],mx1[j-1][k+1]+k-j+1);
            }
            else f[now][1][j][k]=-inf;
         
         
        for(j=2;j<m;j++)mx2[j][j]=f[pre][1][j][j];
        for(j=1;j<m;j++)
            for(k=2;k<m-j;k++)
            mx2[k][k+j]=max(mx2[k][k+j-1],max(mx2[k+1][k+j],f[pre][1][k][k+j]));
 
        for(j=1;j<m;j++)for(k=j+2;k<=m;k++){
            if(sm[i][k]==sm[i][j-1])
                f[now][2][j][k]=max(f[pre][2][j][k],mx2[j+1][k-1])+k-j+1;
            else f[now][2][j][k]=-inf;
            if(f[now][2][j][k]>ans)ans=f[now][2][j][k];
        }
    }
    printf("%d\n",ans);
    return 0;
}
T2

<T3>

题意:求最多有几对字符串相匹配,A与T配,G与C配。

技术分享图片
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
#define ull unsigned long long
using namespace std;
const int maxn=1e5+233,modd=2333333;
struct zs{ull v;int pre,rest;}e[maxn];int tot,last[modd];
char s[maxn];
int i,j,k,n,m;


int ra,fh;char rx;
inline int read(){
    rx=getchar(),ra=0,fh=1;
    while(rx<0)rx==-&&(fh=-1),rx=getchar();
    while(rx>=0)ra=ra*10+rx-48,rx=getchar();return ra*fh;
}

inline bool tryget(ull v){
    int x=v%modd,i;
    for(i=last[x];i&&e[i].v!=v;i=e[i].pre);
    return (i&&e[i].rest)?(e[i].rest--,1):0;
}
inline void ins(ull v){
    int x=v%modd,i;
    for(i=last[x];i&&e[i].v!=v;i=e[i].pre);
    if(i)e[i].rest++;else e[++tot].v=v,e[tot].rest=1,e[tot].pre=last[x],last[x]=tot;
}
int mp1[255];
int main(){
    freopen("T8_.in","r",stdin);
    freopen("T8_.out","w",stdout);
    n=read();
    mp1[A]=0,mp1[T]=1,mp1[C]=2,mp1[G]=3;
    int ans=0;
    for(i=1;i<=n;i++){
        scanf("%s",s+1);
        ull h1=0,h2=0;int len=strlen(s+1),ch;
        for(j=1;j<=len;j++)
            ch=mp1[(int)s[j]],
            h1=h1*2333+ch+1,h2=h2*2333+(ch^1)+1;
        if(tryget(h2))ans++;else ins(h1);
    }printf("%d\n",ans);
}
T 3

<T4>

蒟蒻忘了开long long 啊!!

解法:从任意一点出发找到离他最远的点,那么找到的这个点必然为树的直径的某一端点,顺着这个端点我们就能找到直径的令一个端点,

那么树上所有点到其他点的距离必然是到直径的某个端点的距离,那么分别DFS直径的两个端点,每个点到直径两个端点的距离取个max值即可。

技术分享图片
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 100050
using namespace std;
#define int long long
int tot,n,dp[maxn],head[maxn],maxlen,len,fan;
int read(){
    int w=0,f=1;char c=getchar();
    while(c<0||c>9) if(c==-) f=-1,c=getchar();
    while(c>=0&&c<=9) w=w*10+c-48,c=getchar();;
    return w*f;
}
struct Edge{
    int to,next,v;
}e[200050];
void add(int x,int y,int v){
    e[++tot]=(Edge){y,head[x],v};head[x]=tot;
}
void dfs(int x,int fa,int len){
    if(len>maxlen) maxlen=len,fan=x;
    for(int i=head[x];i;i=e[i].next){
        if(e[i].to!=fa){
            dfs(e[i].to,x,len+e[i].v);
            dp[e[i].to]=max(dp[e[i].to],len+e[i].v);
        }
    }
}
#undef int
int main(){
    #define int long long
    freopen("T3_.in","r",stdin);
    freopen("T3_.out","w",stdout);
    int i,x,v;
    n=read();
    for(i=1;i<=n;i++){
        x=read();v=read();add(i,x,v);add(x,i,v);
    }
    memset(dp,0,sizeof(dp));
    dfs(1,-1,0);
    dfs(fan,-1,0);
    dfs(fan,-1,0);
//    dfs(fan,-1,0);
//    dfs(fan,-1,0);
//    dfs(fan,-1,0);
//    dfs(fan,-1,0);
//    dfs(fan,-1,0);
//    dfs(fan,-1,0);
    for(i=1;i<=n;i++)
    printf("%lld\n",dp[i]);
    fclose(stdin);fclose(stdout);
    return 0;
}
T4

 

以上是关于JSZX Winter Camp Day 3 爆零记的主要内容,如果未能解决你的问题,请参考以下文章

Winter Camp 2016游记

2019 wannafly winter camp

冬令营 Winter Camp搜索专题

2020 Petrozavodsk Winter Camp, Jagiellonian U Contest 部分题解

2020 Petrozavodsk Winter Camp, Jagiellonian U Contest 部分题解

冬令营 Winter Camp数学专题