• Codeforces Round #517(Div. 1) 题解


    A.Cram Time

    显然$a,b$都是被用完的,我们也只会用一个前缀。

    #include <bits/stdc++.h>
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    #define M 100005
    int n,m;
    
    vector <int> p,q;
    
    inline bool check(int x) {return 1ll*x*(1+x)/2<=n+m;}
    
    int main () {
        //freopen("a.in","r",stdin);
        n=read(),m=read();
        int l=1,r=1e5,mid,ans=0;
        while (l<=r) {
            mid=l+r>>1;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        
        FOR2(ans,1,i) 
            if(n>=i) n-=i,q.push_back(i);
            else m-=i,p.push_back(i);
        int size=q.size();
        printf("%d
    ",size);
        for1(1,size,i) printf("%d ",q[i-1]);
        puts("");
        size=p.size();
        printf("%d
    ",size);
        for1(1,size,i) printf("%d ",p[i-1]);
        puts("");
    }
    View Code

    B.Minimum path

    我们一定是把某条路径的前几个不是$a$的变成$a$。

    dp出来最长的$a$的前缀长度,然后把所有满足条件的点都保存下来。

    之后逐位贪心,因为$dis$不断增大,所以是$O(n^2)$的。

    #include <bits/stdc++.h>
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    #define M 2005
    int n,m;
    char a[M][M];
    int f[M][M],size;
    bool vis[M][M];
    struct node {int x,y;}q[M*M],p[M*M];
    
    inline bool check(int c) {
        c+='a'-1;
        for1(1,size,i) {
            int x=q[i].x;
            int y=q[i].y;
            if(a[x+1][y]==c||a[x][y+1]==c) return 1;
        }
        return 0;
    }
    
    inline void move_(int c) {
        c+='a'-1;
        int cnt=0;
        for1(1,size,i) {
            int x=q[i].x;
            int y=q[i].y;
            if(a[x+1][y]==c&&!vis[x+1][y]) vis[x+1][y]=1,p[++cnt]=(node){x+1,y};
            if(a[x][y+1]==c&&!vis[x][y+1]) vis[x][y+1]=1,p[++cnt]=(node){x,y+1};
        }
        size=cnt;
        for1(1,size,i) q[i]=p[i];
    }
    
    int main () {
        //freopen("a.in","r",stdin);
        n=read(),m=read();
        for1(1,n,i) scanf("%s",a[i]+1);
        if(m>=2*n-1) {
            for1(1,2*n-1,i) putchar('a');
            puts("");
            return 0;
        }
        
        memset(f,0x3f,sizeof(f));
        f[1][1]=a[1][1]!='a';
        for1(1,n,i) for1(1,n,j) {
            int c=a[i][j]!='a';
            if(i-1) f[i][j]=min(f[i][j],f[i-1][j]+c);
            if(j-1) f[i][j]=min(f[i][j],f[i][j-1]+c);
        }
        
        int da=0;
        for1(1,n,i) for1(1,n,j) if(f[i][j]<=m) da=max(da,i+j-1);
        for1(1,n,i) for1(1,n,j) if(i+j-1==da&&f[i][j]<=m) q[++size]=(node){i,j};
        for1(1,da,i) putchar('a');
        if(f[1][1]>m) q[++size]=(node){1,1},da=1,putchar(a[1][1]);
        for1(da+1,2*n-1,i) {
            int x=1;
            while (!check(x)) ++x;
            move_(x);
            putchar('a'+x-1);
        }
        puts("");
    }
    View Code

    C.Triple Flips

    我觉得我学习了一种很好的思路。

    当看到题解的一刻我觉得这个题很不好。

    但是当我仔细分析之后我觉得这是一种非常正确且有效的思路。

    首先我们对于$n$很小的点可以暴力状压,发现$nleq 7$才可能无解。

    接下来我们就考虑题目中给出的上界$left lfloor frac{n}{3} ight floor+12$。

    我们可以理解为每一步操作至少使得端点为$1$的序列长度减$3$,之后当长度变小时就可以用状压了。

    然后就很简单了。

    #include <bits/stdc++.h>
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    #define M 200005
    int n;
    bool vis[M];
    int a[M],tot,e_size,head[M],dis[M];
    
    set <pair<int,int> > q;
    struct node {int v,nxt;}e[M*2];
    struct point {int x,y,z;}cc[M];
    
    inline void e_add(int u,int v) {
        e[++e_size]=(node){v,head[u]};
        head[u]=e_size;
    }
    
    inline void add_(int x,int y) {
        a[x]^=1,a[y]^=1,a[2*y-x]^=1;
        cc[++tot]=(point){x,y,2*y-x};
    }
    
    inline void solve() {
        int m=min(n,12);
        int all=(1<<m)-1;
        for1(0,all,i) {
            for1(1,m,j) {
                for1(j+1,m,k) if(2*k-j<=m) e_add(i,i^(1<<j-1)^(1<<k-1)^(1<<2*k-j-1));
            }
        }
        memset(dis,0x3f,sizeof(dis));
        dis[0]=0;
        q.insert(make_pair(0,0)); 
        while (!q.empty()) {
            auto t=*q.begin();
            q.erase(q.begin());
            if(vis[t.second]) continue;
            vis[t.second]=1;
            for(int i=head[t.second];i;i=e[i].nxt) {
                int v=e[i].v;
                if(dis[v]>dis[t.second]+1) {
                    dis[v]=dis[t.second]+1;
                    q.insert(make_pair(dis[v],v));
                }
            }
         }
    }
    
    inline void trans_(int pre,int Max,int x) {
        if(!x) return;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dis[x]==dis[v]+1) {
                int cnt=0;
                int buc[3]={0};
                FOR2(Max,1,j) if((x^v)>>j-1&1) buc[cnt++]=Max-j+1+pre;
                add_(buc[0],buc[1]);
                trans_(pre,Max,v);
                return;
            }
        }
    }
    
    int main () {
    //    freopen("a.in","r",stdin);
        n=read();
        for1(1,n,i) a[i]=read();
        solve();
        if(n<=12) {
            int zt=0;
            for1(1,n,i) zt=zt*2+a[i];
            if(dis[zt]>n) puts("NO");
            else {
                puts("YES");
                trans_(0,n,zt);
                printf("%d
    ",tot);
                for1(1,tot,i) printf("%d %d %d
    ",cc[i].x,cc[i].y,cc[i].z);
            }
            return 0;
        }
        puts("YES");
        for(int i=1;i<=n-12;) {
            while (!a[i]&&i!=n) ++i;
            if(i>n-12) break;
            if(!a[i+1]) {
                if(a[i+2]) add_(i,i+2);
                else add_(i,i+3);
            }
            else {
                if(a[i+2]) add_(i,i+1);
                else {
                    int cnt=0;
                    int buc[3]={0};
                    for1(i+3,i+5,j) if(a[j]) buc[cnt++]=j;
                    if(!cnt) {
                        add_(i,i+6),add_(i+1,i+7);
                    }
                    else if(cnt==1) {
                        add_(i,buc[0]),add_(i+1,i+6);
                    }
                    else if(cnt==2) {
                        add_(i,buc[0]),add_(i+1,buc[1]);
                    }
                    else {
                        add_(i+1,i+3),add_(i,i+4);
                    }
                }
            }
        }
        
        int zt=0;
        for1(1,12,i) a[i]=a[n-12+i];
        for1(1,12,i) zt=zt*2+a[i];
        
        trans_(n-12,12,zt);
        printf("%d
    ",tot);
        for1(1,tot,i) printf("%d %d %d
    ",cc[i].x,cc[i].y,cc[i].z);
    }
    View Code

    D.Familiar Operations

    令$x=prod pi^{ai}$。

    我们可以$dfs$出所有把$ai$排序之后的序列,即本质不同的序列。

    你会发现操作数并不会很多,所以并不用$dfs$出太多。

    我之后直接用了$floyd$来搞$dis$,然后枚举到多少个因子就行了。

    感觉自己好蠢,我总是想不到边权相同时直接$Bfs$是线性的。

    #include <bits/stdc++.h>
    #include <unordered_map>
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long unll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    #define M 3005
    #define mod 76543
    #define N 1000005
    bool vis[N];
    int sta[M],zt[N];
    int A[M],dis[M][M];
    int cnt,a[M][10],f[M],s[N],g[N][10];
    int x_[10]={0,2,3,5,7,11,13,17,19};
    
    unordered_map <unll,int> st;
    
    inline void max(int &x,int y) {if(x<y) x=y;}
    inline void min(int &x,int y) {if(x>y) x=y;}
    
    inline void dfs(int x,int d,ll sum) {
        if(x==9) {
            f[++cnt]=d;
            for1(0,8,i) a[cnt][i]=sta[i];
            unll t=0;
            for1(1,8,i) if(sta[i]) t=t*mod+sta[i];
            st[t]=cnt;
            return;
        }
        
        for1(0,sta[x-1],i) {
            sta[x]=i;
            dfs(x+1,d*(i+1),sum);
            sum*=x_[x];
            if(sum>200000000) break;
        }
    }
    
    inline int get_(int x) {
        int now=x;
        int b[10]={0};
        for1(1,s[x],i) {
            int y=g[x][i];
            while (!(now%y)) now/=y,++b[i];
        }
        sort(b+1,b+s[x]+1);
        
        unll t=0;
        FOR2(s[x],1,i) t=t*mod+b[i];
        return st[t];
    }
    
    int main () {
    //    freopen("a.in","r",stdin);
        sta[0]=30;
        dfs(1,1,1);
        
        memset(dis,0x3f,sizeof(dis));
        for1(1,cnt,i) dis[i][i]=0;
        for1(1,cnt,i) {
            for1(1,8,j) {
                if(a[i][j]+1>a[i][j-1]) continue;
                unll x=0;
                ++a[i][j];
                for1(1,8,k) if(a[i][k]) x=x*mod+a[i][k];
                --a[i][j];
                if(st.count(x)) {
                    int t=st[x];
                    dis[i][t]=dis[t][i]=1;
                }
            }
        }
        
        for1(1,cnt,i) 
            for1(1,cnt,j) if(dis[j][i]<100) 
                for1(1,cnt,k) if(dis[i][k]<100) 
                    min(dis[j][k],dis[j][i]+dis[i][k]);
        
        for1(1,cnt,i) {
            for1(1,cnt,j) A[j]=dis[i][j],dis[i][j]=1e9;
            for1(1,cnt,j) min(dis[i][f[j]],A[j]);
        }
        
        for1(2,N-5,i) {
            if(s[i]) continue;
            int x=i;
            while (x+4<N) g[x][++s[x]]=i,x+=i;
        }
        
        
        int size=0;
        for1(1,cnt,i) if(!vis[f[i]]) vis[f[i]]=1,zt[++size]=f[i];
        
        int Test_=read();
        while (Test_--) {
            int x=read(),y=read();
            x=get_(x),y=get_(y);
            int ans=1e9;
            for1(1,size,i) min(ans,dis[x][zt[i]]+dis[y][zt[i]]);
            printf("%d
    ",ans);
        }
    }
    View Code

    E.Rain Protection

    思路感觉还是很简单了,就是自己太蠢了,一开始思路错了结果打了好几个版本那个思路。

    我们只保存可到达的$(x,0)$的区间。

    令$x$为到$i$时的位置,$y$为$i-1$的某个位置,$g(x,i)=x+frac{h*(p[i].x-x)}{p[i].y}$即对面线上的横坐标。

    那么我们需要满足的条件是:

    egin{cases}
    & ext  lleq y leq r \
    & ext  y-v*tleq x leq y+v*t \
    & ext  g(y,i)-v*tleq g(x,i-1)leq g(y,i)+v*t
    end{cases}

    并且式子可以化成$k1*y+b1leq x leq k2*y+b2$的形式。

    这样解出来就是之后$x$的范围了。

    观察式子其实就是以$y$为横坐标会出来一个平行四边形(或者两条平行线)。

    直接找到满足横坐标范围内的纵坐标的$min,max$就行了。

    好迷啊,必须要加$eps$才能过。

    #include <bits/stdc++.h>
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define for1(a,b,i) for(int i=a;i<=b;++i)
    #define FOR2(a,b,i) for(int i=a;i>=b;--i)
    using namespace std;
    typedef long long ll;
    inline int read() {
        int f=1,sum=0;
        char x=getchar();
        for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
        for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
        return f*sum;
    }
    
    #define M 200005
    #define eps 1e-10
    int n,w,h,e1,e2;
    
    struct node {
        double l,r;
    };
    
    struct point {
        int t;
        double x,y;
        
        inline void in() {
            t=read(),x=read(),y=read();
        }
    }p[M];
    
    inline bool check(double v) {
        node a,t,tmp;
        a.l=a.r=e1;
        for(int i=1,las=0;i<=n;las=p[i].t,++i) {
            las=p[i].t-las;
            
            double k[4]={0,1-h/p[i-1].y,1-h/p[i].y,1-h/p[i-1].y};
            double b[4]={0,h*p[i-1].x/p[i-1].y-las*v,h*p[i].x/p[i].y,h*p[i-1].x/p[i-1].y+las*v};
            
            b[3]-=b[2],k[3]/=k[2],b[3]/=k[2];
            b[1]-=b[2],k[1]/=k[2],b[1]/=k[2];
            
            tmp.l=1e9,tmp.r=-1e9;
            
            t.l=max(a.l-las*v,k[3]*a.l+b[3]);
            t.r=min(a.l+las*v,k[1]*a.l+b[1]);
            if(t.l<t.r+eps) tmp.l=min(tmp.l,t.l),tmp.r=max(tmp.r,t.r);
            
            t.l=max(a.r-las*v,k[3]*a.r+b[3]);
            t.r=min(a.r+las*v,k[1]*a.r+b[1]);
            if(t.l<t.r+eps) tmp.l=min(tmp.l,t.l),tmp.r=max(tmp.r,t.r);
            
            if(k[3]!=1) {
                double x=(b[3]+las*v)/(1-k[3]);
                if(x>a.l&&x<a.r) {
                    x-=las*v;
                    tmp.l=min(tmp.l,x),tmp.r=max(tmp.r,x);
                }
                x=(las*v-b[3])/(k[3]-1);
                if(x>a.l&&x<a.r) {
                    x+=las*v;
                    tmp.l=min(tmp.l,x),tmp.r=max(tmp.r,x);
                }
            }
            if(k[1]!=1) {
                double x=(las*v-b[1])/(k[1]-1);
                if(x+eps>a.l&&x<a.r+eps) {
                    x+=las*v;
                    tmp.l=min(tmp.l,x),tmp.r=max(tmp.r,x);
                }
                x=(las*v+b[1])/(1-k[1]);
                if(x+eps>a.l&&x<a.r+eps) {
                    x-=las*v;
                    tmp.l=min(tmp.l,x),tmp.r=max(tmp.r,x);
                }
            }
            
            a=tmp;
            
            tmp.r=h*p[i].x/(h-p[i].y);
            tmp.l=(w*p[i].y-p[i].x*h)/(p[i].y-h);
            
            a.l=max(a.l,tmp.l);
            a.r=min(a.r,tmp.r);
            
            a.l=max(a.l,0),a.r=min(a.r,w);
            
            if(a.l>a.r+eps) return 0;
        }
        return 1;
    }
    
    int main () {
        //freopen("a.in","r",stdin);
        n=read(),w=read(),h=read(),e1=read(),e2=read();
        
        p[0].x=(e1+e2)/2.0,p[0].y=h/2.0;
        for1(1,n,i) p[i].in();
        
        double l=0,r=1e3+5,mid;
        for1(1,100,i) {
            mid=(l+r)/2;
            if(check(mid)) r=mid;
            else l=mid;
        }
        if(r>1000) puts("-1");
        else printf("%.10f
    ",r);
    }
    View Code
  • 相关阅读:
    UI/UE对个性化推荐的影响
    毫秒转换为天、小时、分、秒
    查生字
    探秘推荐引擎之协同过滤算法小综述
    给文献添加上标
    雅可比迭代和高斯赛德尔迭代
    广义二项式定理求解系数
    关于最大流的EdmondsKarp算法详解
    海量数据处理利器之布隆过滤器
    [leetcode] Path sum路径之和
  • 原文地址:https://www.cnblogs.com/asd123www/p/9843693.html
Copyright © 2020-2023  润新知