csps-模拟7980题解

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

树:ios

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

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

 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\n",res);
52     }
53     return 0;
54 }
View Code

环:spa

我没脸抄的方程3d

 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\n",ans);
31     return 0;
32 }
View Code

礼物: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\n",2*ans%mod);
44     return 0;
45 }
View Code

最长不降低子序列:
htm

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

 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\n",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\n",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\n",ans);
86         return 0;
87     }
88     return 0;
89 }
View Code

彻底背包问题:ci

同余系最短路,咕咕

 

 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\n",ans);
78         }
79     }
80     return 0;
81 }
View Code