zoukankan      html  css  js  c++  java
  • CSP-S全国模拟赛第三场 【nan死了】

    mmt

    居然第一步膜化乘除 都没看出来,没救了...

    大概是贡献前缀和优化的做法

    巨兔式讲解:大家都学会了么?

    咱发现有大量的 (i/j , i%j ) 同时 对很多 c 产生了贡献,咱可以去优化这一部分的转移,具体做法就是根据前面能加的后面也能加,然后一路累加且算贡献

    对于小于根号的所有 i/j ,咱可以优化这一部分转移,然后对于大于根号的 i/j ,暴力算就好了,两者复杂度都是是 n 根号 n 的

    //by Judge
    #include<bits/stdc++.h>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
    #define ll long long
    #define eps 1e-8
    using namespace std;
    const int mod=123456789;
    const int M=1e5+3;
    typedef int arr[M];
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } char sr[1<<21],z[20];int CCF=-1,Z;
    inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
    inline void print(int x,char chr='
    '){
    	if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
    	while(z[++Z]=x%10+48,x/=10);
    	while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
    } int n,bl; arr a,b,c; double inv[M];
    #define Div(x,y) (int(x*inv[y]+eps))
    int main(){ n=read(),bl=sqrt(n);
    	fp(i,1,n) inv[i]=1.0/i,a[i]=read(); fp(i,0,n-1) b[i]=read();
    	fp(x,1,bl) fp(y,0,x-1){ Rg ll now=-1; Rg int A,l,r; // i/j = x 步长 , y 初始位置 
    		for(Rg int k=x+y;k<=n;k+=x) if(Div(k,Div(k,x))==x){ // 必须是可达状态 ,此时 j = k/x 
    			if(now<0) l=r=Div(k,x),A=k%r,now=1ll*a[x]*b[A]%mod;
    			else{ ++r; if(Div(k,l)!=i) ++l; else A=k%l,now=(now+1ll*a[x]*b[A])%mod; }
    			c[k]=(c[k]+now)%mod; // 当前的 now 存在的之前的状态当前 k 也可达 
    		}
    	}
    	fp(i,1,n) fp(j,1,i) if(Div(i,j)<=bl) break;
    		else c[i]=(c[i]+1ll*a[Div(i,j)]*b[i%j]%mod)%mod;
    	fp(i,1,n) print(c[i]); return Ot(),0;
    }
    

    Sabotage

    艹...这 T2 ,真 tm 长芝士了 ,支配树的新奇打法...

    一眼看不出是支配树,只觉得题面眼熟,然后发现其实算法更加熟...

    然后发现支配树代码很长,调挂了,于是康康题解区对比找找自己哪里挂了,于是有了这次惊人的发现

    可以说是支配树板子题辣,这里的常规做法就不说了,又臭又长 (艹)

    这里用的方法很诡(qiao)异(miao),大概就是说咱把这个 DAG 缩一下,对于入度大于 2 的节点把 Fa 设为 所有父亲节点的 LCA ,求解的时候输出两个点 LCA 的深度就好了,至于两个点不在同一棵树上(或者是别的无解情况),是可以被非常自然的处理掉的(雾),于是正确性就有了感性理解下的保证

    然后咱可以发现这里的 LCA 是要随着拓扑的进行可以同时维护的...所以就打不了小常数的树剖了,于是顺便重温了一下倍增 LCA (雾)

    具体康康代码咯?

    卡了下常,进了 Rank1 (可能您康到咱的代码之后就不是了)

    //by Judge
    #include<cstdio>
    #include<iostream>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(Rg int i=head[u],v=e[i].to;i;v=e[i=e[i].nxt].to)
    using namespace std;
    const int M=1e5+7;
    typedef int arr[M];
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } char sr[1<<21],z[20];int C=-1,Z;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    inline void print(int x,char chr='
    '){
        if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]=chr;
    } int n,m,pat,hd,tl,f[M][19]; arr head,lg,q,h,d;
    struct Edge{ int to,nxt; }e[M<<1];
    inline void add(int x,int y){ ++d[y];
    	e[++pat]=(Edge){y,head[x]},head[x]=pat;
    }
    inline int LCA(int u,int v){ if(h[u]>h[v]) swap(u,v);
    	for(Rg int i=0;h[v]-h[u];++i) if(((h[v]-h[u])>>i)&1) v=f[v][i]; if(u==v) return u;
    	fd(i,17,0) if(f[u][i]^f[v][i]) u=f[u][i],v=f[v][i]; return *f[u];
    }
    int main(){ n=read(),m=read(),lg[0]=-1;
    	Rg int x,y; fp(i,1,m) x=read(),y=read(),add(y,x);
    	fp(i,1,n) lg[i]=lg[i>>1]+1,*f[i]=!d[i]?q[++tl]=i,0:-1;
    	while(hd<tl){ x=q[++hd],h[x]=h[*f[x]]+1;
    		fp(i,1,lg[h[x]]) f[x][i]=f[f[x][i-1]][i-1];
    		go(x) *f[v]=*f[v]<0?x:LCA(x,*f[v]),!--d[v]&&(q[++tl]=v);
    	} m=read(); while(m--) x=read(),y=read(),print(h[LCA(x,y)]);
    	return Ot(),0;
    }
    

    LP

    并没有什么特别的? 但是咱太菜了还是想不出来的那种

    (看了题解后)不难想出 (n*p^2) 的 SB dp 方程 ,f[i][j][k]

    看着数据范围应该是 np 的题目(NP-hard 可海星),那么怎么少掉一个 p ?

    咱发现两个限制本质上是可以简化的,可以把 f 简化为 2 维的 f[i][j] ,j 表示对于选出的 b 之和小于等于 j 且 c 之和大于等于 j

    然后两个转移方式(x 为 0 或 1)的 dp 转移,然后一个单调队列优化 x=1 时的转移就好了

    空间继续优化,那么滚动可以解决,并且开数组变小了,代码常数却并没有怎么提高,所以隐隐起到了卡常的效果(空间小一般时间也会小,原因显而易见)

    //by Judge
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
    #define QwQ printf("IMPOSSIBLE!!!
    ")
    #define QvQ printf("%d
    ",f[n&1][p])
    using namespace std;
    const int inf=2e9+7;
    const int M=1e4+3;
    typedef int arr[M];
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    inline bool cmin(int& a,int b){return a>b?a=b,1:0;}
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } int n,p,head,tail,x,y; arr a,b,c,f[2],q,w;
    inline void Solv(){ n=read(),p=read(); fp(i,1,n) a[i]=read();
    	fp(i,1,n) b[i]=read(); fp(i,1,n) c[i]=read(); fp(i,1,p) f[0][i]=inf;
    	fp(i,1,n){ head=1,tail=0,x=i&1,y=x^1; fp(j,0,p) f[x][j]=f[y][j];
    		fp(j,a[i],p){ while(head<=tail&&w[tail]>=f[y][j-a[i]]) --tail;
    			while(head<=tail&&q[head]<j-b[i]) ++head;
    			q[++tail]=j-a[i],w[tail]=f[y][q[tail]],cmin(f[x][j],w[head]+c[i]);
    		}
    	} f[n&1][p]<inf?QvQ:QwQ;
    }
    int main(){ int T=read();
    	while(T--) Solv(); return 0;
    }
    

    明天继续吧...

  • 相关阅读:
    poj 1015 Jury Compromise(背包+方案输出)
    最长公共上升子序列 (poj 2127) (Greatest Common Increasing Subsequence)
    轮廓线DP:poj 2279 Mr. Young's Picture Permutations
    LCS的几种求法
    POJ 1737 Connected Graph(高精度+DP递推)
    Cats transport(codeforces311B)(斜率优化)
    高精度(压位+判负数+加减乘+读写)
    洛谷 P2257 YY的GCD
    [POI2007]ZAP-Queries (莫比乌斯反演+整除分块)
    [SDOI2010]古代猪文 (欧拉,卢卡斯,中国剩余)
  • 原文地址:https://www.cnblogs.com/Judge/p/11714165.html
Copyright © 2011-2022 走看看