CSPS分数取mod赛92-93
作者:互联网
我好菜啊。。。。。
92只会打暴力,93暴力都不会了
模拟92,
T1:直接ex_gcd加分类讨论即可
T2:考场只会打暴搜,正解为排序后线段树解决,排序的关键字为a+b,因为如果ai<bj&&bi<aj那么i应该在j前。
1 #include<bits/stdc++.h> 2 #define N 100050 3 #define LL long long 4 using namespace std; 5 int n,pd[N],cnt,lsh[N<<1],ls; 6 long long dp[N],ans; 7 struct node{ 8 int a,b,w; 9 friend bool operator <(const node &x,const node &y) 10 { 11 return x.a+x.b<y.a+y.b; 12 } 13 }q[N]; 14 inline void init() 15 { 16 for(int i=1;i<=n;++i)lsh[++ls]=q[i].a,lsh[++ls]=q[i].b; 17 sort(lsh+1,lsh+ls+1);ls=unique(lsh+1,lsh+ls+1)-lsh-1; 18 for(int i=1;i<=n;++i){ 19 q[i].a=lower_bound(lsh+1,lsh+ls+1,q[i].a)-lsh; 20 q[i].b=lower_bound(lsh+1,lsh+ls+1,q[i].b)-lsh; 21 }sort(q+1,q+n+1); 22 } 23 LL ma[N<<3],tag[N<<3]; 24 inline void plu(int g,LL w){ma[g]+=w,tag[g]+=w;} 25 inline void upd(int g){ma[g]=max(ma[g<<1],ma[g<<1|1]);} 26 inline void down(int g){plu(g<<1,tag[g]),plu(g<<1|1,tag[g]);tag[g]=0;} 27 void add(int g,int l,int r,int x,int y,int w) 28 { 29 if(l>y||r<x)return;if(l>=x&&r<=y)return plu(g,w); 30 if(tag[g])down(g);const int m=l+r>>1; 31 add(g<<1,l,m,x,y,w);add(g<<1|1,m+1,r,x,y,w); 32 upd(g); 33 } 34 void change(int g,int l,int r,int pos,LL w) 35 { 36 if(l==r)return (void)(ma[g]=max(ma[g],w)); 37 if(tag[g])down(g);const int m=l+r>>1; 38 if(pos<=m)change(g<<1,l,m,pos,w); 39 else change(g<<1|1,m+1,r,pos,w); 40 upd(g); 41 } 42 LL ask(int g,int l,int r,int x,int y) 43 { 44 if(l>y||r<x)return 0; 45 if(l>=x&&r<=y)return ma[g]; 46 if(tag[g])down(g); 47 const int m=l+r>>1; 48 const LL a1=ask(g<<1,l,m,x,y),a2=ask(g<<1|1,m+1,r,x,y); 49 return max(a1,a2); 50 } 51 inline void duizhangkuaipao() 52 { 53 for(int i=1;i<=n;++i) 54 { 55 dp[i]=ask(1,1,ls,1,min(q[i].a,q[i].b))+q[i].w; 56 add(1,1,ls,q[i].a,q[i].b,q[i].w); 57 change(1,1,ls,q[i].a,dp[i]); 58 } 59 ans=ma[1]; 60 } 61 int main() 62 { 63 scanf("%d",&n); 64 for(int i=1;i<=n;++i) 65 scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].w); 66 init(); 67 duizhangkuaipao(); 68 cout<<ans<<endl; 69 }View Code
T3:多源点最短路,对于每个点维护到这个点的最短距离和对应的特殊点是那个,在扫描每条边时更新答案即可
1 #include<bits/stdc++.h> 2 #define N 200050 3 #define LL long long 4 using namespace std; 5 int n,m,p,a[N],pd[N],bl[N]; 6 const LL inf=10000000000000000; 7 LL dis[N],ans[N]; 8 int he[N],ne[N<<2],to[N<<2],w[N<<2],tot; 9 inline void work1() 10 { 11 for(int i=1,x,y,z;i<=m;++i){ 12 scanf("%d%d%d",&x,&y,&z); 13 ans[x]=min(ans[x],(LL)z); 14 ans[y]=min(ans[y],(LL)z); 15 } 16 for(int i=1;i<=p;++i)printf("%lld ",ans[a[i]]); 17 } 18 inline void addedge(int x,int y,int z) 19 { 20 to[++tot]=y;ne[tot]=he[x]; 21 w[tot]=z;he[x]=tot; 22 } 23 priority_queue<pair<LL,int> >q; 24 #define mmp make_pair 25 #define fir first 26 #define sec second 27 inline void getans() 28 { 29 for(int i=0;i<=n;++i)dis[i]=inf; 30 for(int i=1;i<=p;++i) 31 dis[a[i]]=0,bl[a[i]]=a[i],q.push(mmp(0,a[i])); 32 LL d;int g; 33 while(q.size()) 34 { 35 g=q.top().sec; 36 d=-q.top().fir; 37 q.pop(); 38 if(dis[g]!=d)continue; 39 // printf("g:%d d:%lld\n",g,d); 40 for(int i=he[g];i;i=ne[i]){ 41 if(bl[g]&&bl[to[i]]&&bl[to[i]]!=bl[g]){ 42 // printf("g:%d to:%d blg:%d blt:%d new:%lld\n",g,to[i],bl[g],bl[to[i]],d+w[i]+dis[to[i]]); 43 ans[bl[g]]=min(ans[bl[g]],d+w[i]+dis[to[i]]); 44 ans[bl[to[i]]]=min(ans[bl[to[i]]],d+w[i]+dis[to[i]]); 45 } 46 if(dis[to[i]]>d+w[i]){ 47 dis[to[i]]=d+w[i];bl[to[i]]=bl[g]; 48 q.push(mmp(-dis[to[i]],to[i])); 49 } 50 } 51 } 52 } 53 inline void work2() 54 { 55 56 57 } 58 int main() 59 { 60 // freopen("distance.in","r",stdin); 61 // freopen("my.out","w",stdout); 62 scanf("%d%d%d",&n,&m,&p); 63 for(int i=1;i<=p;++i)scanf("%d",&a[i]),ans[a[i]]=inf,pd[a[i]]=1; 64 if(p==n){work1();return 0;} 65 for(int i=1,x,y,z;i<=m;++i) 66 { 67 scanf("%d%d%d",&x,&y,&z); 68 addedge(x,y,z);addedge(y,x,z); 69 } 70 getans(); 71 for(int i=1;i<=p;++i) 72 printf("%lld ",ans[a[i]]); 73 }View Code
模拟92,
T1:一眼二分,测大样例发现答案不连续,化一下式子发现是个三维偏序,打个cdq上去A掉。
正解为按a的前缀和排序,把b离散化,在树状数组中插入原数组下标,复杂度为nlogn
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 500050 6 #define LL long long 7 using namespace std; 8 int n,ans=1; 9 LL sb[N],lsh[N<<1]; 10 int a[N],b[N],c[N],ls; 11 inline int read(){ 12 int s=0,b=0;char c=getchar(); 13 while(c>'9'||c<'0'){if(c=='-')b=1;c=getchar();} 14 while(c>='0'&&c<='9')s=s*10+c-'0',c=getchar(); 15 if(b)return -s; 16 return s; 17 } 18 struct node{LL a;int b,id;}q[N],qq[N]; 19 inline void init() 20 { 21 sort(lsh+1,lsh+ls+1); 22 ls=unique(lsh+1,lsh+ls+1)-lsh-1; 23 for(int i=0;i<=n;++i) 24 q[i].b=lower_bound(lsh+1,lsh+ls+1,sb[i])-lsh; 25 } 26 inline void add(int x,const int v){ 27 while(x<=ls){ 28 if(c[x]>v)c[x]=v; 29 x+=x&-x; 30 } 31 } 32 inline void del(int x){while(x<=ls){c[x]=n+10;x+=x&-x;}} 33 inline int ask(int x) 34 { 35 int ret=n+10; 36 while(x) 37 { 38 if(c[x]<ret)ret=c[x]; 39 x-=x&-x; 40 } 41 return ret; 42 } 43 inline void CDQ(int l,int r) 44 { 45 if(l==r)return; 46 const int m=l+r>>1; 47 CDQ(l,m);CDQ(m+1,r); 48 register int i=l,j=m+1,t,o=l; 49 while(j<=r) 50 { 51 while(i<=m&&q[j].a>=q[i].a){ 52 add(q[i].b,q[i].id); 53 qq[o++]=q[i++]; 54 } 55 t=q[j].id-ask(q[j].b); 56 if(t>ans)ans=t; 57 qq[o++]=q[j++]; 58 } 59 for(int k=l;k<i;++k)del(q[k].b); 60 while(i<=m)qq[o++]=q[i++]; 61 for(int i=l;i<=r;++i)q[i]=qq[i]; 62 } 63 int main() 64 { 65 scanf("%d",&n); 66 lsh[++ls]=0; 67 for(int i=1,x;i<=n;++i)q[i].a=q[i-1].a+read(),q[i].id=i; 68 for(int i=1,x;i<=n;++i)lsh[++ls]=sb[i]=sb[i-1]+read(),c[i]=n+10; 69 c[0]=n+10; 70 init(); 71 for(int i=n;i<=ls;++i)c[i]=n+10; 72 CDQ(0,n); 73 printf("%d\n",ans); 74 }View Code
T2:暴力做法为区间dp,dp[i][j]表示区间[i,j]的答案,for枚举长度,for枚举区间左端点,for枚举根节点复杂度为O(n3)
利用决策单调性优化。发现在一个已有区间的右面插入一个点,原树的根不会左移。同理在右面插入,决策点不会右移。
dp的同时记录决策点即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 5050 6 #define LL long long 7 using namespace std; 8 int n,rt=1,po[N][N]; 9 const LL inf=1ll<<50; 10 LL sum[N]; 11 LL ans,dp[N][N]; 12 int main() 13 { 14 scanf("%d",&n); 15 for(int i=1,x;i<=n;++i)scanf("%d",&x),sum[i]=sum[i-1]+x; 16 for(int i=1;i<=n;++i)dp[i][i]=sum[i]-sum[i-1],po[i][i]=i; 17 for(int len=2;len<=n;++len){ 18 for(int i=1,j;i+len-1<=n;++i){ 19 j=i+len-1;dp[i][j]=inf; 20 for(int k=po[i][j-1];k<=po[i+1][j];++k) 21 if(dp[i][k-1]+dp[k+1][j]<=dp[i][j]){dp[i][j]=dp[i][k-1]+dp[k+1][j],po[i][j]=k;} 22 dp[i][j]+=sum[j]-sum[i-1]; 23 } 24 } 25 printf("%lld\n",dp[1][n]); 26 }View Code
T3:高斯消元,期望题一般逆推。题解:
我们首先考虑单个的 k。设 fi 表示从 i 出发第一次到 k 的期望步数,那么
f k =0,f i =sigma(f j )/x i +1 (i!=k,j 为 i 的所有出边,x i 为 i 的出度),用高斯消元解出 f1 即可。
分治消元的具体做法是:先用前一半的方程进行消元,然后递归后一半;
(恢复原矩阵后)再用后一半的方程进行消元,然后递归前一半。这样当区间缩小到
单点时,这个方程并没有拿来消其它的方程,我们可以直接修改它并求出所有f i 。
类似思想可以参考我这篇题解:https://www.cnblogs.com/loadingkkk/p/11272338.html
1 #include<cstdio> 2 #include<iostream> 3 #define N 320 4 #define LL long long 5 using namespace std; 6 const int mod=998244353; 7 int n,m,inv[500050]; 8 LL a[N][N],c[11][N][N],b[N],dd[11][N],ans[N]; 9 inline int qpow(int d,int z) 10 { 11 int ret=1; 12 for(;z;z>>=1,d=1ll*d*d%mod) 13 if(z&1)ret=1ll*ret*d%mod; 14 return ret; 15 } 16 inline void init(int n){for(int i=1;i<=n;++i)inv[i]=qpow(i,mod-2);} 17 int he[N],ne[500050],to[500050],d[N],tot; 18 inline void addedge(int x,int y) 19 { 20 to[++tot]=y;++d[x]; 21 ne[tot]=he[x];he[x]=tot; 22 } 23 inline void Gauss(int l,int r,int x,int y) 24 { 25 for(int i=l;i<=r;++i) 26 { 27 const LL iv=qpow(a[i][i],mod-2); 28 for(int j=1;j<=n;++j) 29 { 30 if(j==i||!a[j][i])continue; 31 const LL pl=iv*a[j][i]%mod; 32 for(int o=x;o<=y;++o){ 33 a[j][o]-=a[i][o]*pl%mod; 34 if(a[j][o]<0)a[j][o]+=mod; 35 } 36 b[j]-=b[i]*pl%mod; 37 if(b[j]<0)b[j]+=mod; 38 } 39 } 40 } 41 inline void solve(int dep,int l,int r) 42 { 43 if(l==r){ans[l]=b[1]*qpow(a[1][1],mod-2)%mod;return;} 44 for(int i=1;i<=n;dd[dep][i]=b[i],++i) 45 for(int j=1;j<=n;++j) 46 c[dep][i][j]=a[i][j]; 47 const int m=l+r>>1; 48 Gauss(l,m,l,r);solve(dep+1,m+1,r); 49 for(int i=1;i<=n;b[i]=dd[dep][i],++i) 50 for(int j=1;j<=n;++j) 51 a[i][j]=c[dep][i][j]; 52 Gauss(m+1,r,l,r);solve(dep+1,l,m); 53 } 54 inline void work() 55 { 56 for(register int i=1;i<=n;++i){ 57 a[i][i]=b[i]=mod-1; 58 for(register int j=he[i];j;j=ne[j]) 59 (a[i][to[j]]+=inv[d[i]])%=mod; 60 } 61 solve(1,1,n); 62 } 63 int main() 64 { 65 // freopen("walk.in","r",stdin); 66 scanf("%d%d",&n,&m);init(m); 67 for(int i=1,x,y;i<=m;++i){ 68 scanf("%d%d",&x,&y); 69 addedge(x,y); 70 } 71 work(); 72 for(int i=2;i<=n;++i)printf("%lld\n",ans[i]); 73 }View Code
希望下一次能考好吧
标签:92,int,LL,CSPS,long,Code,93,include,define 来源: https://www.cnblogs.com/loadingkkk/p/11763034.html