CSP-S 模拟测试 45 题解

由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了。

考试过程:

到新机房的第一次考试,貌似海星?

第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来发现只要每个人都有怪兽打就吼了,然后显然二分答案,1h 打完。

T2没什么思路,想拆柿子,但没什么用,只qj了链的测试点,用来跑所有测试点竟然得了40pts。

T3一眼看错题,然后一眼wqs二分,然后调到考试结束也没调出样例。

题解:

T1 kill:

先把人和怪兽得坐标sort一下。

显然这n个人打怪兽的最长时间是单调的,然后直接二分答案即可,check时贪心的选择前面的怪兽。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 const int N=5005;
 5 int mon[N],per[N];
 6 int maxn;
 7 int n,m,s;
 8 bool check(int mid){
 9     int res=0,now=1;
10     for(int i=1;i<=n;++i){
11         while(now<=m&&mid<abs(mon[now]-s)+abs(per[i]-mon[now])) ++now;
12 //        res+=abs(mon[now]-s)+abs(per[i]-mon[now]);
13         if(now>m/*n||m*/) return 0;now++;
14     }
15     return 1;
16 }
17 
18 signed main(){
19     scanf("%lld%lld%lld",&n,&m,&s);
20     for(int i=1;i<=n;++i) scanf("%lld",&per[i]);
21     for(int i=1;i<=m;++i) {scanf("%lld",&mon[i]);maxn=max(maxn,mon[i]);}
22     int l=0,r=maxn;
23     sort(per+1,per+n+1);
24     sort(mon+1,mon+m+1);
25     int ans=0;
26     while(l<=r){
27 //        cout<<l<<" "<<r<<endl;
28         int mid=(l+r)>>1;
29         if(check(mid)) r=mid-1,ans=mid;
30         else l=mid+1;
31     }
32     printf("%lld",ans);
33 }
34 /*
35 //jia tanxin
36 #include<bits/stdc++.h>
37 #define int long long
38 using namespace std;
39 const int N=5005;
40 int per[N],mon[N],cost[N];
41 vector<int > ve[N];
42 set<int > s[N];
43 int max(int a,int b){
44     return a>b?a:b;
45 }
46 
47 signed main(){
48 //freopen("data.in","r",stdin);
49 //freopen("1.out","w",stdout);
50     int n,m,s;
51     scanf("%lld%lld%lld",&n,&m,&s);
52     for(signed i=1;i<=n;++i) scanf("%lld",&per[i]);
53     for(signed i=1;i<=m;++i) scanf("%lld",&mon[i]);
54     for(signed i=1;i<=m;++i){
55         cost[i]=abs(mon[i]-s);
56     }
57     for(signed i=1;i<=n;++i){
58         for(signed j=1;j<=m;++j){
59             ve[i].push_back(cost[j]+abs(per[i]-mon[j]));
60         }
61     }
62     for(signed i=1;i<=n;++i){
63         sort(ve[i].begin(),ve[i].end());
64     }
65     int ans=0;
66     for(signed i=1;i<=n;++i){
67         ans=max(ans,*ve[i].begin());
68     }
69     printf("%d",ans);
70 }
71 */
kill

T2 beauty:

类似于换根dp的思路,分别考虑子树内和子树外的点对产生的贡献,记$cnt[x]$ 为以$x$为根节点的子树内关键点的个数,那么对于,每个点,考虑所有的关键点在这一个点产生的贡献,子树内有$cnt[x]$个,那么子数外就有$2*k-cnt[x]$个,那么这些点配对的话,经过这一个点,即经过一个单位的距离,产生贡献就是$min(cnt[x],2*k-cnt[x])$,$dfs$一遍即可。

  1 #include<bits/stdc++.h>
  2 #define int long long
  3 using namespace std;
  4 const int N=1e5+10;
  5 int d[N],fa[N][22];
  6 int first[N],nex[N<<1],to[N<<1],tot;
  7 int ka[N],ver[N],du[N],Root;
  8 int mark[N],cnt[N];
  9 int dp[N];
 10 int n,k,QJ,ans;
 11 struct Ver{
 12     int dep,id;
 13 }p[N];
 14 bool cmp(Ver a,Ver b){
 15     return a.dep<b.dep;
 16 }
 17 void add(int a,int b){
 18     to[++tot]=b,nex[tot]=first[a],first[a]=tot;
 19 }
 20 queue<int > q;
 21 void bfs(){
 22     d[Root]=1;
 23     q.push(Root);
 24     while(q.size()){
 25         int x=q.front();q.pop();
 26         for(int i=first[x];i;i=nex[i]){
 27             int y=to[i];
 28             if(d[y]) continue;
 29             d[y]=d[x]+1;
 30             fa[y][0]=x;
 31             for(int j=1;j<=20;++j) fa[y][j]=fa[fa[y][j-1]][j-1];
 32             q.push(y);
 33         }
 34     }
 35 }
 36 int Lca(int x,int y){
 37     if(d[x]>d[y]) swap(x,y);
 38     for(int i=20;i>=0;--i) if(d[fa[y][i]]>=d[x]) y=fa[y][i];
 39     if(x==y) return x;
 40     for(int i=20;i>=0;--i) if(fa[y][i]!=fa[x][i]) y=fa[y][i],x=fa[x][i];
 41     return fa[x][0];
 42 }
 43 void pre_dfs(int x,int fa){
 44     if(mark[x]) cnt[x]=1;
 45     for(int i=first[x];i;i=nex[i]){
 46         int y=to[i];
 47         if(y==fa) continue;
 48         pre_dfs(y,x);
 49         cnt[x]+=cnt[y];
 50     }
 51 }
 52 
 53 void dfs(int x,int fat){
 54     if(mark[x]) cnt[x]++;
 55     for(int i=first[x];i;i=nex[i]){
 56         int y=to[i];
 57         if(y==fat) continue;
 58         dfs(y,x);
 59         cnt[x]+=cnt[y];
 60     }
 61     ans+=min(cnt[x],k*2-cnt[x]);
 62 //    dp[fa[x][0]]=min(dp[x],k*2-cnt[x]);
 63 }
 64 
 65 signed main(){
 66     scanf("%lld%lld%lld",&n,&k,&QJ);
 67     const int bz=k<<1;
 68     for(int i=1;i<=bz;++i) {scanf("%lld",&ver[i]);mark[ver[i]]=1;}
 69     for(int i=1;i<n;++i){
 70         int x,y;
 71         scanf("%lld%lld",&x,&y);
 72         add(x,y);
 73         add(y,x);
 74         du[x]++,du[y]++;
 75     }
 76     if(QJ){
 77         for(int i=1;i<=n;++i){
 78             if(du[i]==1){
 79                 Root=i;
 80                 break;
 81             }
 82         }
 83         bfs();
 84         for(int i=1;i<=bz;++i){
 85             ka[i]=d[ver[i]];
 86             p[i].dep=d[ver[i]];
 87             p[i].id=ver[i];
 88         }
 89         sort(p+1,p+k*2+1,cmp);
 90         for(int i=1;i<=k;++i){
 91             ans+=abs(p[i].dep+p[bz-i+1].dep-2*d[Lca(p[i].id,p[bz-i+1].id)]);
 92         }
 93         printf("%lld",ans);
 94     }
 95     else{
 96         Root=1;
 97         memset(dp,0x7f,sizeof(dp));
 98         dfs(1,0);
 99         printf("%lld",ans);
100     }
101 }
102 /*
103 7 2 0
104 1 5 6 2
105 1 3
106 3 2
107 4 5
108 3 7
109 4 3
110 4 6
111 */
beauty

T3 wight:

考试时看错题,以为只要有一个最小生成树包含那条边即可,但实际上是要所有的最小生成树都要包含那条边。

我们可以先用kruscal 跑出一个最小生成树,那么他现在树边已经在最小生成树上了,所以我们对树边和非树边进行分类讨论。

对于非树边,因为只有树边才会被他替换下去,所以我们考虑树边对他的影响,考虑这条非树边两个端点的简单路径,加上这条非树边就会构成一个环,对于一个环,任意去掉一条边他还能够连接起n个点,所以这条非树边只要不是这个环上最大权值就可以,即MST上路径最大权值,树剖维护即可,然后把这条非树边本来的权值更新到线段树里边,后面树边情况要用到。

对于树边,我们考虑非树边对他的影响,同上,所有能够与他成环的非树边,只要有权值比他小的,就可以把它替换掉,所以每条树边的答案是所有与他成环的非树边的最小值减一,还是树剖维护。

注意:

  1. 要先更新完所有的非树边再更新树边,因为你不知道那条非树边会对那条树边产生影响。
  2. 各种编号的转化一定要搞清楚。
  3. 关于线段树的操作,建树和询问维护的是树边`最大值,更新和懒标记下传是非树边`最小值。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int INF=1e9;
      4 const int N=1e6+10;
      5 int first_f[N],tot,first[N],tot_c,ans[N];
      6 int n,m;
      7 int rcd[N];
      8 struct Edge{
      9     int fr,to,nex,val,id,v;
     10 }e[N<<1];
     11 struct EDGE{
     12     int fr,to,nex,val,id;
     13 }ee[N<<1];
     14 
     15 struct SegmentTree{
     16     int l,r,lazy,mx,mi;
     17 }tr[N<<2];
     18 int f[N];
     19 int get(int x){
     20     if(f[x]==x) return x;
     21     return f[x]=get(f[x]);
     22 }
     23 
     24 void add(int x,int y,int z,int k){
     25     e[tot].id=k,e[tot].to=y,e[tot].fr=x;
     26     e[tot].nex=first_f[x],e[tot].val=z,first_f[x]=tot++;
     27 //    e[tot].to=b,e[tot].id=kl,e[tot].fr=a,e[tot].nex=first_f[a],e[tot].val=c,first_f[a]=tot++;
     28 }
     29 bool cmp(Edge a,Edge b){
     30     return a.val<b.val;
     31 }
     32 void add_c(int a,int b,int c,int kl){
     33     ee[tot_c].to=b,ee[tot_c].nex=first[a],ee[tot_c].val=c,ee[tot_c].id=kl,first[a]=tot_c++;
     34 }
     35 
     36 int fa[N],d[N],size[N],son[N],wt[N];
     37 void dfs1(int x,int fat){//cout<<x<<endl;
     38     size[x]=1;
     39     for(int i=first[x];i!=-1;i=ee[i].nex){
     40         int y=ee[i].to;
     41         if(y==fat) continue;
     42         d[y]=d[x]+1;//cout<<x<<" "<<y<<endl;
     43         fa[y]=x;
     44         wt[ee[i].to]=ee[i].val;
     45         rcd[ee[i].to]=ee[i].id;
     46         dfs1(y,x);
     47         size[x]+=size[y];
     48         if(size[y]>size[son[x]]) son[x]=y;
     49     }
     50 }
     51 int id[N],top[N],cnttt,pos[N];
     52 void dfs2(int x,int topf){//cout<<x<<" "<<topf<<endl;
     53     top[x]=topf;
     54     id[x]=++cnttt;
     55     pos[cnttt]=x;
     56     if(son[x]) dfs2(son[x],topf);
     57     for(int i=first[x];i!=-1;i=ee[i].nex){
     58         int y=ee[i].to;
     59         if(y==fa[x]||y==son[x]) continue;
     60         dfs2(y,y);
     61     }
     62 }
     63 void down(int p){
     64     if(tr[p].lazy==INF+1) return ;
     65     tr[p<<1].lazy=min(tr[p<<1].lazy,tr[p].lazy);
     66     tr[p<<1|1].lazy=min(tr[p<<1|1].lazy,tr[p].lazy);
     67     tr[p<<1].mi=min(tr[p].lazy,tr[p<<1].mi);
     68     tr[p<<1|1].mi=min(tr[p].lazy,tr[p<<1|1].mi);
     69     tr[p].lazy=INF+1;
     70 }
     71 
     72 void build(int p,int l,int r){
     73     tr[p].l=l,tr[p].r=r,tr[p].lazy=INF+1;
     74     if(l==r){
     75         tr[p].mi=INF+1;
     76         tr[p].mx=wt[pos[l]];
     77         return ;
     78     }
     79     int mid=(l+r)>>1;
     80     build(p<<1,l,mid);
     81     build(p<<1|1,mid+1,r);
     82     tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
     83 }
     84 int q_mx=0;
     85 void update(int p,int l,int r,int ll,int rr,int val){//cout<<"U "<<p<<endl;
     86     if(ll<=l&&r<=rr){
     87         tr[p].mi=min(tr[p].mi,val);
     88         tr[p].lazy=min(tr[p].lazy,val);
     89         return ;
     90     }
     91     down(p);
     92     int mid=(tr[p].l+tr[p].r)>>1;
     93     if(ll<=mid) update(p<<1,l,mid,ll,rr,val);
     94     if(rr>mid) update(p<<1|1,mid+1,r,ll,rr,val);
     95     tr[p].mi=min(tr[p<<1].mi,tr[p<<1|1].mi);
     96 }
     97 void query(int p,int l,int r,int ll,int rr){//cout<<p<<" "<<l<<" "<<r<<" "<<ll<<" "<<rr<<endl;
     98     if(ll<=l&&r<=rr){
     99         q_mx=max(q_mx,tr[p].mx);
    100         return ;
    101     }
    102     down(p);
    103     int mid=(tr[p].l+tr[p].r)>>1;
    104     if(ll<=mid) query(p<<1,l,mid,ll,rr);
    105     if(rr>mid) query(p<<1|1,mid+1,r,ll,rr);
    106 }
    107 void Update(int x,int y,int val){
    108     while(top[x]!=top[y]){//cout<<x<<" "<<y<<endl;
    109         if(d[top[x]]<d[top[y]]) swap(x,y);
    110         update(1,1,n,id[top[x]],id[x],val);
    111         x=fa[top[x]];
    112     }
    113     if(d[x]>d[y]) swap(x,y);
    114     update(1,1,n,id[x]+1,id[y],val);
    115 }
    116 int ans_mi=0x7fffffff,ans_mx=0;
    117 int Ask(int x,int y){
    118     q_mx=0,ans_mx=0;
    119     while(top[x]!=top[y]){//cout<<x<<" "<<y<<endl;
    120         if(d[top[x]]<d[top[y]]) swap(x,y);
    121         q_mx=0;
    122         query(1,1,n,id[top[x]],id[x]);
    123         ans_mx=max(ans_mx,q_mx);
    124         x=fa[top[x]];
    125     }//cout<<"K"<<endl;
    126     if(d[x]>d[y]) swap(x,y);
    127     q_mx=0;
    128     query(1,1,n,id[x]+1,id[y]);
    129     ans_mx=max(ans_mx,q_mx);
    130     return ans_mx;
    131 }
    132 
    133 void db(int p){
    134     cout<<tr[p].l<<" "<<tr[p].r<<" "<<tr[p].mx<<endl;
    135     if(tr[p].l==tr[p].r){
    136         return ;
    137     }
    138     db(p<<1);db(p<<1|1);
    139 }
    140 void solve(int p){
    141     if(tr[p].l==tr[p].r){
    142         ans[rcd[pos[tr[p].l]]]=tr[p].mi-1;
    143         if(ans[rcd[pos[tr[p].l]]]==INF){
    144             ans[rcd[pos[tr[p].l]]]=-1;
    145         }
    146         return ;
    147     }
    148     down(p);
    149     solve(p<<1);solve(p<<1|1);
    150 }
    151 
    152 int main(){
    153     int Suarez;
    154     memset(first,-1,sizeof(first));
    155     scanf("%d%d%d",&n,&m,&Suarez);
    156     for(int i=1;i<=n;++i) f[i]=i;
    157     for(int i=1;i<=m;++i){
    158         int x,y,z;
    159         scanf("%d%d%d",&x,&y,&z);
    160         add(x,y,z,i);
    161 //        add(y,x,z,i);
    162     }
    163     sort(e+0,e+tot,cmp);
    164     int sum=0;
    165     for(int i=0;i<tot;i++){
    166         int x=(get(e[i].fr)),y=get(e[i].to);
    167         if(x!=y){//cout<<i<<" ";
    168             if(get(x)!=get(y)) f[x]=y;
    169             sum++;
    170             e[i].v=1;
    171             add_c(e[i].fr,e[i].to,e[i].val,e[i].id);
    172             add_c(e[i].to,e[i].fr,e[i].val,e[i].id);
    173         }
    174         if(sum==n-1) break;
    175     }
    176     d[1]=1;
    177     dfs1(1,0);//cout<<"Dfs1"<<endl;
    178     dfs2(1,1);//cout<<"dfs2"<<endl;
    179     build(1,1,n);//cout<<"build"<<endl;
    180 //    db(1);
    181 //    for(int i=1;i<=n;++i) cout<<first[i]<<" ";
    182 //    puts("");
    183 //    for(int i=0;i<tot;++i) cout<<e[i].v<<" ";
    184 //    for(int i=1;i<=n;++i) cout<<top[i]<<" ";
    185 //    cout<<endl;
    186 //    for(int i=1;i<=n;++i) cout<<fa[i]<<" ";
    187 //    for(int i=1;i<=n;++i) cout<<wt[pos[i]]<<" ";
    188 //    cout<<endl;
    189 //    cout<<tot<<endl;
    190 //    for(int i=1;i<=n;++i) cout<<son[i]<<" ";
    191 //    cout<<endl;
    192     for(int i=0;i<tot;i++){
    193 //        if(i==19) cout<<"L"<<endl;
    194 //        if(i==tot-1) cout<<"L"<<endl;
    195 //        if(i>40) cout<<e[i].v<<" ";
    196         if(e[i].v==0){//cout<<i<<endl;
    197             ans[e[i].id]=Ask(e[i].fr,e[i].to)-1;//cout<<"ask"<<endl;
    198             Update(e[i].fr,e[i].to,e[i].val);//cout<<"upd"<<endl;
    199         }
    200     }
    201 //    for(int i=0;i<tot;++i) cout<<e[i].v<<" ";
    202     solve(1);
    203     for(int i=1;i<=m;++i){
    204         printf("%d ",ans[i]);
    205     }
    206 }
    207 /*
    208  4 4 0
    209  1 2 1
    210  2 3 1
    211  3 4 1
    212  4 1 2
    213 
    214  out 1 1 1 0
    215 
    216  4 3 0
    217  1 2 2
    218  2 3 2
    219  3 4 2
    220 
    221  out -1 -1 -1
    222 
    223 */
    wight
原文地址:https://www.cnblogs.com/leom10/p/11574900.html