11.18总结

T1:找规律+构造 规律挺好找的 构造有点细 还好写对了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,k,st[50];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        if(!k){puts("YES");puts("0");continue;}
        if(!(k&1)){puts("NO");continue;}
        puts("YES");
        int tot=log2(k)+1;
        printf("%d\n",tot);
        int del=((1<<tot)-1-k)>>1;
        memset(st,0,sizeof(st));
        for(int i=0,pre=0,now=1,dlt=0;i<tot;i++){
            if(del&(1<<i)) pre+=(1<<i+1),dlt+=(1<<i);
            else{
                st[i]+=now-pre+dlt;
                if(dlt){
                    int j=0,nxt=st[i]+(1<<i),cnt=0,x=dlt;
                    while(x) cnt++,x-=(x&-x);
                    while(dlt) st[i-cnt+j]=nxt-(dlt&-dlt),dlt-=(dlt&-dlt),nxt=st[i-cnt+j],j++;
                }
            }now+=(1<<i);
        }for(int i=0;i<tot;i++) printf("%d ",st[i]);
        puts("");
    }return 0;
}
View Code

T2:最短路 为多个关键点找最近关键点

考场上直接想成二进制分组了(见过一道类似的题目),然后光荣TLE30

正解是一遍dij后记录每个点被哪个关键点更新,然后枚举每条边更新答案即可

#include<bits/stdc++.h>
using namespace std;
#define N 300005
#define M 500005
#define P pair<int,int>
#define fi first
#define se second
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline int rd(){
    int x=0,f=1;char c=gc();
    for(;c>'9'||c<'0';c=gc()) if(c=='-') f=0;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-48;
    return f?x:-x;
}int n,lst[N],st[M<<1],ed[M<<1],nxt[M<<1],len[M<<1],tot,m,k,id[N],dis[N],vis[N],ans[N],f[N];
inline void add_e(int x,int y,int z){ed[++tot]=y,st[tot]=x,nxt[tot]=lst[x],lst[x]=tot,len[tot]=z;}
priority_queue<P,vector<P>,greater<P> >q;
inline void dijkstra(int x){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=k;i++) q.push(P(0,id[i])),dis[id[i]]=0;
    while(!q.empty()){
        int u=q.top().se;q.pop();
        if(vis[u]) continue;vis[u]=1;
        for(int i=lst[u];i;i=nxt[i]){
            if(!vis[ed[i]]&&dis[ed[i]]>dis[u]+len[i]){
                dis[ed[i]]=dis[u]+len[i];
                if(f[ed[i]]!=ed[i]) f[ed[i]]=f[u];
                q.push(P(dis[ed[i]],ed[i]));
            }
        }
    }
}int main(){
    n=rd(),m=rd(),k=rd();
    memset(ans,0x3f,sizeof(ans));
    for(int i=1;i<=m;i++){
        int x=rd(),y=rd(),z=rd();
        add_e(x,y,z);add_e(y,x,z);
    }for(int i=1;i<=k;i++) f[id[i]=rd()]=id[i];
    dijkstra(1);
    for(int i=1;i<=tot;i+=2){
        if(f[st[i]]==f[ed[i]]) continue;
        int d=dis[st[i]]+len[i]+dis[ed[i]];
        ans[f[st[i]]]=min(ans[f[st[i]]],d);
        ans[f[ed[i]]]=min(ans[f[ed[i]]],d);
    }for(int i=1;i<=k;i++) printf("%d ",ans[id[i]]==0x3f3f3f3f?-1:ans[id[i]]);
    return 0;
}
View Code

T3:字符串哈希 本来应该能过的 毕竟已经非常接近正解了 只是脑子出了点问题

没有考虑到拿较长串的哈希值相减,而是拿较短串的哈希值加上拼接段,复杂度就变成了20000方乘上log,TLE70

#include<bits/stdc++.h>
using namespace std;
#define N 2005
#define M 20005
#define mod 998244353
#define ll long long
#define sd 131
int n,m,p,q,r;char s[M][N],t[M][N];
ll ht[M],hd[M],hs[M],ans,pw[N];unordered_map<ll,int>mp;
inline void Hsh(int x){
    ll t1=1,h1=0;
    for(int i=1;i<=r-q;i++) (t1*=sd)%=mod;
    for(int i=1;i<=q;i++) (h1+=t1*t[x][i]%mod)%=mod,(t1*=sd)%=mod;
    ht[x]=h1;
}inline void hshd(int x){
    ll t1=1,h1=0;
    for(int i=r+1;i<=p;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod;
    hd[x]=h1;
}inline void hsh(int x,int y){
    ll t1=1,h1=0;
    for(int i=y;i<=r;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod;
    for(int i=1;i<y;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod;
    hs[x]=h1;
}int main(){
    scanf("%d%d%d%d",&n,&m,&p,&q);r=(p+q)>>1;
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    for(int i=1;i<=m;i++) scanf("%s",t[i]+1);
    for(int i=1;i<=m;i++) Hsh(i);
    for(int i=1;i<=n;i++) hshd(i);pw[0]=1;
    for(int i=1;i<=r;i++) pw[i]=pw[i-1]*sd%mod;
    ll inv=922042494;
    for(int j=1;j<=m;j++) mp[ht[j]]++;
    for(int i=1;i<=n;i++){
        ll lst=-1;hsh(i,1);
        for(int j=1;j<=r;j++){
            if(lst!=hs[i]) ans+=mp[(hs[i]+mod-hd[i])%mod];
            lst=hs[i];
            (hs[i]+=mod-s[i][j])%=mod;
            (hs[i]+=s[i][j]*pw[r]%mod)%=mod;
            (hs[i]*=inv)%=mod;
        }
    }printf("%lld",ans);
    return 0;
}
View Code

T4:找找规律,很容易发现只有选择一条权值全为1的链或两段1由一个2连接可能成为最优答案(若无权为1的点就直接选权值最小即可) 简单换根dp 考场上没怎么看啧

#include<bits/stdc++.h>
using namespace std;
#define N 1000005
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf,pt[1005],Z;
inline int rd(){
    int x=0,f=1;char c=gc();
    for(;c>'9'||c<'0';c=gc()) if(c=='-') f=0;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-48;
    return f?x:-x;
}int n,lst[N],ed[N<<1],nxt[N<<1],val[N],tot,f[N],mx[N],se[N],ans,ans1;
inline void add_e(int x,int y){ed[++tot]=y,nxt[tot]=lst[x],lst[x]=tot;}
void dfs(int x,int fa){
    for(int i=lst[x];i;i=nxt[i]){
        if(ed[i]==fa) continue;
        dfs(ed[i],x);
        if(f[ed[i]]>mx[x]) se[x]=mx[x],mx[x]=f[ed[i]];
        else if(f[ed[i]]>se[x]) se[x]=f[ed[i]];
    }if(val[x]==1){
        f[x]=mx[x]+1;
        ans=max(ans,f[x]+se[x]);
    }
}void dfs1(int x,int fa){
    if(x!=1){
        int tmp=mx[fa]+1;
        if(f[x]==mx[fa]) tmp=se[fa]+1;
        if(mx[x]<tmp) se[x]=mx[x],mx[x]=tmp;
        else if(se[x]<tmp) se[x]=tmp;
        f[x]=mx[x]+1;
    }if(val[x]==2) if(mx[x]==se[x]) ans1=max(ans1,mx[x]+se[x]+1);
    for(int i=lst[x];i;i=nxt[i]){
        if(ed[i]==fa) continue;
        dfs1(ed[i],x);
    }
}int main(){
    n=rd();
    for(int i=1;i<n;i++){
        int x=rd(),y=rd();
        add_e(x,y);add_e(y,x);
    }int mn=0x3f3f3f3f;
    for(int i=1;i<=n;i++) val[i]=rd(),mn=min(mn,val[i]);
    if(mn>1) return printf("%d/1\n",mn),0;
    dfs(1,0);dfs1(1,0);
    if(ans*2>=ans1) printf("1/%d",ans);
    else printf("2/%d",ans1);
    return 0;
}
View Code

 

 

posted on 2021-11-19 08:44  Aurora-Sley  阅读(45)  评论(0)    收藏  举报



Live2D