zoukankan      html  css  js  c++  java
  • csps-模拟7980题解

    题面:https://www.cnblogs.com/Juve/articles/11712702.html

    树:

    我太sb了不知道DROT是1,还在sb找根

    记录一个fa[]数组,表示x的祖先中第一个智商比x大的,用栈维护

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define re register
     6 using namespace std;
     7 const int MAXN=1e5+5;
     8 int n,q,w[MAXN],sta[MAXN],top=0,rb[MAXN],topp=0,fa[MAXN],deep[MAXN];
     9 int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
    10 inline void add(re int u,re int v){
    11     ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
    12 }
    13 void dfs(int x,int f){
    14     deep[x]=deep[f]+1;
    15     int res=0;
    16     while(w[x]>w[sta[top]]){
    17         rb[++topp]=sta[top];
    18         --top,++res;
    19     }
    20     fa[x]=sta[top];
    21     sta[++top]=x;
    22     for(int i=pre[x];i;i=nxt[i]){
    23         int y=to[i];
    24         if(y==f) continue;
    25         dfs(y,x);
    26     }
    27     --top;
    28     while(res){
    29         sta[++top]=rb[topp--];
    30         --res;
    31     }
    32 }
    33 signed main(){
    34     scanf("%d%d",&n,&q);
    35     for(re int i=1;i<=n;++i) scanf("%d",&w[i]);
    36     for(re int i=1,u,v;i<n;++i){
    37         scanf("%d%d",&u,&v);
    38         add(u,v),add(v,u);
    39     }
    40     w[0]=0x7fffffff;sta[++top]=0;
    41     dfs(1,0);
    42     for(re int i=1,u,v,c,res;i<=q;++i){
    43         scanf("%d%d%d",&u,&v,&c);
    44         res=0;
    45         if(c<w[u]) c=w[u],++res;
    46         while(deep[u]>=deep[v]){
    47             if(c<w[u]) c=w[u],++res;
    48             u=fa[u];
    49         }
    50         if(c<w[v]) ++res;
    51         printf("%d
    ",res);
    52     }
    53     return 0;
    54 }
    View Code

    环:

    我没脸抄的方程

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 using namespace std;
     7 const int MAXN=1e5+5,mod=1e9+7;
     8 int n,e,p[MAXN],q[MAXN],ans;
     9 int q_pow(int a,int b,int p){
    10     int res=1;
    11     while(b){
    12         if(b&1) res=res*a%p;
    13         a=a*a%p;
    14         b>>=1;
    15     }
    16     return res;
    17 }
    18 signed main(){
    19     scanf("%lld%lld",&n,&e);
    20     for(int i=1;i<=n;++i) q[i]=n-1;
    21     for(int i=1,u,v;i<=e;++i){
    22         scanf("%lld%lld",&u,&v);
    23         ++p[u],--q[u],--q[v];
    24     }
    25     ans=n*(n-1)%mod*(n-2)%mod*q_pow(6,mod-2,mod)%mod;
    26     for(int i=1;i<=n;++i){
    27         int res=p[i]*(p[i]-1)%mod*q_pow(2,mod-2,mod)%mod+p[i]*q[i]%mod*q_pow(2,mod-2,mod)%mod+q[i]*(q[i]-1)%mod*q_pow(8,mod-2,mod)%mod;
    28         ans=(ans-res+mod)%mod;
    29     }
    30     printf("%lld
    ",ans);
    31     return 0;
    32 }
    View Code

    礼物:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 #define re register
     7 using namespace std;
     8 const int mod=1e9+7,MAXN=1e7+5,MAXM=1e7+5;
     9 int n,a[MAXN],b[MAXN],ans;
    10 inline int q_pow(re int a,re int b,re int p){
    11     int res=1;
    12     while(b){
    13         if(b&1) res=res*a%p;
    14         a=a*a%p;
    15         b>>=1;
    16     }
    17     return res;
    18 }
    19 int fac[MAXM<<1],inv[MAXM<<1];
    20 inline void get_c(re int N){
    21     fac[0]=fac[1]=inv[0]=1;
    22     for(int i=2;i<=N;++i) fac[i]=fac[i-1]*i%mod;
    23     inv[N]=q_pow(fac[N],mod-2,mod);
    24     for(int i=N-1;i>=1;--i) inv[i]=inv[i+1]*(i+1)%mod;
    25 }
    26 inline int C(re int n,re int m){
    27     if(m>n) return 0;
    28     if(n==m) return 1;
    29     return fac[n]*inv[m]%mod*inv[n-m]%mod;
    30 }
    31 int maxx=0,tong[MAXM<<2],bas=1e7+3;
    32 signed main(){
    33     scanf("%lld",&n);
    34     for(re int i=1;i<=n;++i){
    35         scanf("%lld%lld",&a[i],&b[i]);
    36         maxx=max(maxx,a[i]+b[i]);
    37     }
    38     get_c(maxx*2+1);
    39     for(int i=1;i<=n;++i){
    40         for(int t=-a[i];t<=b[i];++t) ans=(ans+tong[t+bas]*C(a[i]+b[i],a[i]+t)%mod)%mod;
    41         for(int t=-b[i];t<=a[i];++t) tong[t+bas]=(tong[t+bas]+C(a[i]+b[i],a[i]-t))%mod;
    42     }
    43     printf("%lld
    ",2*ans%mod);
    44     return 0;
    45 }
    View Code

    最长不下降子序列:

    n有1e12,但值域150,发现它是循环的,处理循环节即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 using namespace std;
     7 const int MAXN=1e6+5;
     8 int n,t,a,b,c,d,p[MAXN],ans=0,maxx=0,cc[MAXN];
     9 int lowbit(int x){
    10     return x&(-x);
    11 }
    12 void update(int pos,int val){
    13     for(int i=pos;i<=maxx;i+=lowbit(i)){
    14         cc[i]=max(cc[i],val);
    15     }
    16 }
    17 int query(int pos){
    18     int res=0;
    19     for(int i=pos;i>0;i-=lowbit(i)){
    20         res=max(res,cc[i]);
    21     }
    22     return res;
    23 }
    24 int vis[MAXN];
    25 signed main(){
    26     scanf("%lld%lld%lld%lld%lld%lld",&n,&t,&a,&b,&c,&d);
    27     if(n<=1000000){
    28         p[1]=maxx=t;
    29         for(int i=2;i<=n;++i){
    30             p[i]=(p[i-1]*p[i-1]%d*a%d+b*p[i-1]%d+c%d)%d;
    31             maxx=max(p[i],maxx);
    32         }
    33         ++maxx;
    34         for(int i=1;i<=n;++i){
    35             int res=query(p[i]+1)+1;
    36             update(p[i]+1,res);
    37             ans=max(ans,res);
    38         }
    39         printf("%lld
    ",ans);
    40         return 0;
    41     }
    42     p[1]=maxx=t;
    43     vis[t]=1;
    44     int pos=0,q=0;//q:xunhuanchangdu
    45     for(int i=2;i<=n;++i){
    46         p[i]=(p[i-1]*p[i-1]%d*a%d+b*p[i-1]%d+c%d)%d;
    47         maxx=max(p[i],maxx);
    48         if(vis[p[i]]){
    49             pos=i;
    50             q=i-vis[p[i]];
    51             break;
    52         }
    53         vis[p[i]]=i;
    54     }
    55     ++maxx;
    56     if(!pos){
    57         //cout<<pos<<endl;
    58         for(int i=1;i<=n;++i){
    59             int res=query(p[i]+1)+1;
    60             update(p[i]+1,res);
    61             ans=max(ans,res);
    62         }
    63         printf("%lld
    ",ans);
    64         return 0;
    65     }else{
    66         int len=n-vis[p[pos]]+1;
    67         int xh=len/q;//xunhuanjici
    68         int ys=len%q;//yuji
    69         for(int i=1;i<=pos-1;++i){
    70             int res=query(p[i]+1)+1;
    71             update(p[i]+1,res);
    72             ans=max(ans,res);
    73         }
    74         for(int k=1;k<=q;++k){
    75             for(int i=pos;i<=min(n,pos+q-1);++i){
    76                 p[i]=p[i-q];
    77                 int res=query(p[i]+1)+1;
    78                 update(p[i]+1,res);
    79                 int tmp=i-pos+1;
    80                 res=res+xh-k-1+(tmp<=ys);
    81                 ans=max(ans,res);
    82             }
    83             pos=pos+q;
    84         }
    85         printf("%lld
    ",ans);
    86         return 0;
    87     }
    88     return 0;
    89 }
    View Code

    完全背包问题:

    同余系最短路,咕咕

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #define int long long
     7 using namespace std;
     8 const int MAXN=55;
     9 int n,m,l,c,v[MAXN],pos,minn=0x3f3f3f3f3f3f3f3f;
    10 int dis[10005],cnt[10005];
    11 queue<int>q;
    12 bool in[10005];
    13 void spfa(){
    14     memset(dis,0x3f,sizeof(dis));
    15     memset(cnt,0x3f,sizeof(cnt));
    16     dis[0]=cnt[0]=0;
    17     in[0]=1;
    18     q.push(0);
    19     while(!q.empty()){
    20         int x=q.front();
    21         q.pop();
    22         in[x]=0;
    23         for(int i=1;i<=n;++i){
    24             int y=(x+v[i])%minn;
    25             if(v[i]>=l&&cnt[x]>=c) break;
    26             if(dis[y]>dis[x]+v[i]){
    27                 dis[y]=dis[x]+v[i];
    28                 if(v[i]>=l) cnt[y]=cnt[x]+1;
    29                 if(!in[y]) q.push(y),in[y]=1;
    30             }else if(dis[y]==dis[x]+v[i]){
    31                 if(cnt[y]>cnt[x]+(v[i]>l)){
    32                     cnt[y]=cnt[x]+1;
    33                     if(!in[y]) q.push(y),in[y]=1;
    34                 }
    35             }
    36         }
    37     }
    38 }
    39 signed main(){
    40     scanf("%lld%lld",&n,&m);
    41     for(int i=1;i<=n;++i){
    42         scanf("%lld",&v[i]);
    43         minn=min(minn,v[i]);
    44     }
    45     scanf("%lld%lld",&l,&c);
    46     sort(v+1,v+n+1);
    47     spfa();
    48     for(int i=1,x;i<=m;++i){
    49         scanf("%lld",&x);
    50         if(dis[x%minn]<=x) puts("Yes");
    51         else puts("No");
    52     }
    53     return 0;
    54 }
    View Code

    最近公共祖先:

    想到了正解,但不会维护subtree(fa[x])-subtree(x)的信息

    考虑dfs序,更新时减去子树x即可

    重复染的点可以直接break

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 using namespace std;
     7 const int MAXN=1e5+5;
     8 int n,m,w[MAXN];
     9 bool vis[MAXN];
    10 int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
    11 void add(int u,int v){
    12     ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
    13 }
    14 int in[MAXN],out[MAXN],fa[MAXN],dfn=0;
    15 void dfs(int x){
    16     in[x]=++dfn;
    17     for(int i=pre[x];i;i=nxt[i]){
    18         int y=to[i];
    19         if(y==fa[x]) continue;
    20         fa[y]=x;
    21         dfs(y);
    22     }
    23     out[x]=dfn;
    24 }
    25 int tr[MAXN<<2],laz[MAXN<<2];
    26 void down(int k){
    27     tr[k<<1]=max(tr[k<<1],laz[k]);
    28     tr[k<<1|1]=max(tr[k<<1|1],laz[k]);
    29     laz[k<<1]=max(laz[k<<1],laz[k]);
    30     laz[k<<1|1]=max(laz[k<<1|1],laz[k]);
    31     laz[k]=0;
    32 }
    33 void update(int k,int l,int r,int opl,int opr,int val){
    34     if(opl<=l&&r<=opr){
    35         tr[k]=max(tr[k],val);
    36         laz[k]=max(laz[k],val);
    37         return ;
    38     }
    39     if(laz[k]) down(k);
    40     int mid=(l+r)>>1;
    41     if(opl<=mid) update(k<<1,l,mid,opl,opr,val);
    42     if(opr>mid) update(k<<1|1,mid+1,r,opl,opr,val);
    43     tr[k]=max(tr[k<<1],tr[k<<1|1]);
    44 }
    45 int query(int k,int l,int r,int opt){
    46     if(l==r) return tr[k];
    47     if(laz[k]) down(k);
    48     int mid=(l+r)>>1;
    49     if(opt<=mid) return query(k<<1,l,mid,opt);
    50     else return query(k<<1|1,mid+1,r,opt);
    51 }
    52 signed main(){
    53     scanf("%lld%lld",&n,&m);
    54     for(int i=1;i<=n;++i){
    55         scanf("%lld",&w[i]);
    56     }
    57     for(int i=1,u,v;i<n;++i){
    58         scanf("%lld%lld",&u,&v);
    59         add(u,v),add(v,u);
    60     }
    61     dfs(1),vis[0]=1;
    62     for(int i=1;i<=m;++i){
    63         char opt[10];
    64         int v,ans;
    65         scanf("%s%lld",opt,&v);
    66         if(opt[0]=='M'){
    67             update(1,1,n,in[v],out[v],w[v]);
    68             vis[v]=1;
    69             while(vis[fa[v]]!=1){
    70                 update(1,1,n,in[fa[v]],in[v]-1,w[fa[v]]);
    71                 update(1,1,n,out[v]+1,out[fa[v]],w[fa[v]]);
    72                 v=fa[v];
    73             }
    74         }else{
    75             ans=query(1,1,n,in[v]);
    76             if(!ans) ans=-1;
    77             printf("%lld
    ",ans);
    78         }
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    [USACO12FEB]牛券Cow Coupons
    合并果子
    序列合并
    中位数
    道路游戏
    教主的花园
    摆花
    hello world之Makefile
    mysql+tomcat+spring 配置心得(从0开始搭环境)
    C#,.Net自动生成大写字母编码
  • 原文地址:https://www.cnblogs.com/Juve/p/11713753.html
Copyright © 2011-2022 走看看