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

希望下一次能考好吧

 

posted @ 2019-10-30 09:44  真-不能AKt♞  阅读(351)  评论(0编辑  收藏  举报