zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",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
    ",ans[i]);
    73 }
    View Code

    希望下一次能考好吧

  • 相关阅读:
    光纤收发器的连接及收发器指示灯故障诊断
    Keepalive介绍及工作原理
    RabbitMQ消息队列集群配置-1
    python2 centos7 安装mysql-python库
    etcd服务的安装与配置 yum安装新版本
    ETCD集群安装配置及简单应用 老版本
    查看mysql 最大连接数,连接线程数
    TCP连接状态详解及TIME_WAIT过多的解决方法
    Linux 进程打开最大文件连接数Too many open files
    redis 连接数 修改
  • 原文地址:https://www.cnblogs.com/loadingkkk/p/11763034.html
Copyright © 2011-2022 走看看