algorithm_group_Round3题解

A. Xiaoxi's Labyrinth (and check)

Topic:

Last time, Xiaoxi played a long time in Gardon's maze castle (see Problem B), and now she also wants to design a maze for Gardon to walk. But her idea of ​​designing a maze is different. First of all, she thinks that all channels should be bidirectionally connected, that is, if there is a channel connecting rooms A and B, then you can use it to walk from room A to room B Through it, walk from room B to room A. In order to increase the difficulty, Xiaoxi hopes that any two rooms have only one path that can be connected (unless they go back). Xiaoxi will give you her design now, let you help determine whether her design is in line with her design ideas.

answer:

That is, to judge whether a graph is in a loop, and use a check set to achieve, when the two nodes to be merged belong to a set, output NO

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<unordered_map>
using namespace std;
const int maxn=1e6+14;
const int inf=1e9;
int father[maxn],isRoot[maxn],flag,visit[maxn];
void init () {
    for (int i=0;i<maxn;i++) father[i]=i;
    flag=0;
    fill (isRoot,isRoot+maxn,0);
    fill (visit,visit+maxn,0);
}
int findfather (int x) {
    int a=x;
    while (x!=father[x]) x=father[x];
    while (a!=father[a]) {
        int z=a;
        a=father[a];
        father[z]=x;
    }
    return x;
}
void Union (int a,int b) {
    int faA=findfather(a);
    int faB=findfather(b);
    if (faA!=faB) father[faA]=faB;
}
int main () {
    while (1) {
        int flag=0,x,y;
        init ();
        while (1) {
            scanf ("%d %d",&x,&y);
            if (x==0&&y==0) break; 
            if (x==-1&&y==-1) return 0;
            if (findfather(x)==findfather(y)) flag++;
            visit[x]=1;visit[y]=1;
            Union (x,y);
        }
        for (int i=0;i<maxn;i++) if (visit[i]) isRoot[findfather(i)]++;
        int ans=0;
        for (int i=0;i<maxn;i++) if (isRoot[i]&&visit[i]) ans++;
        if (ans>1) flag++; 
        //printf ("%d\n",ans);
        if (flag==0) printf ("Yes\n");
        else printf ("No\n");
    }
    return 0;
}
View Code

 

B. Eugene and an array (prefix and)

Topic:

If there is a continuous sub-interval and the sum of the interval is 0, then this interval is not good, given an interval to find how many good sub-intervals in this interval

answer:

Traversing from left to right, if the current prefix sum appears in the map, it means that the prefix and the sequence from the previous position to the current position are illegal. It is good to count the sequence of the previous position. Time complexity O (N)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
int a[maxn];
map<ll,ll> pos;
int main () {
    int N;
    scanf("%d",&N);
    pos[0]=1;
    ll sum=0,ans=0,Max=1;
    for (int i=2;i<=N+1;i++) {
        scanf("%d",&a[i]);
        sum+=a[i];
        if (pos[sum]!=0) 
            Max=max(Max,pos[sum]+1);
        ans+=i-Max;
        pos[sum]=i;
    }
    printf("%lld\n",ans);
}
View Code

 

C. Circles of Monsters (prefix and)

Topic:

You are playing another computer game, now you have to kill n monsters. The monsters stand in a circle, numbered from 1 to n clockwise. Initially, the i-th monster has ai health.

You can shoot monsters to kill them. Each shot requires only one bullet and reduces the target monster's health by 1 (inflicting 1 damage to it). In addition, when the health value of a certain monster i becomes 0 or less, it will die and explode, causing bi damage to the next monster (if i if the next monster is already dead, then nothing will happen. The explosion kills the next monster, it will also explode, destroy the monster after the explosion and may trigger another explosion, and so on.

You have to calculate the minimum number of bullets you have to fire to kill all n monsters in the circle.

answer:

Given a circle of monsters, each monster has health and attack power. When you kill a monster, the monster will cause the next monster to equal its attack power, and pass it in turn. When the monster cannot be killed or encountered The dead monster stops. Ask at least how many monsters to kill to kill all monsters.

The method is to open a double array simulation loop, and then open a C array, indicating that each monster is used as a starting point to launch an attack. The number of bullets consumed can derive the state transfer equation:

if (a[i]<=b[i-1])
    c[i]=c[i-1];
else 
    c[i]=c[i-1]+a[i]-b[i-1];
if (i>=N)
    ans=min(ans,c[i]-c[i-N+1]+a[i-N+1]);

Complete code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
int a[maxn];
map<ll,ll> pos;
int main () {
    int N;
    scanf("%d",&N);
    pos[0]=1;
    ll sum=0,ans=0,Max=1;
    for (int i=2;i<=N+1;i++) {
        scanf("%d",&a[i]);
        sum+=a[i];
        if (pos[sum]!=0) 
            Max=max(Max,pos[sum]+1);
        ans+=i-Max;
        pos[sum]=i;
    }
    printf("%lld\n",ans);
}
View Code

 

D. National Road System (Minimal Spanning Tree)

Topic:

Given the x, y coordinates of n cities and the number of people in each city, the owners of these cities want to build the smallest spanning tree. At this time, a magical priest said, I can make a road with a weight value of 0, find A / The maximum value of B, where A is the sum of the number of people in the cities connected by roads with a weight of 0, and B is the weight of the minimum spanning tree.

answer:

Then traverse each pair of vertices, if the edge between the vertices belongs to the minimum spanning tree, then cut the longest path of the pair of vertices in the minimum spanning tree

Otherwise, directly cut the edge connecting the pair of vertices ~

Use the prim algorithm to find the template of the longest path of the minimum spanning tree ~

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=1010;
const int inf=1e9;
double g[maxn][maxn],d[maxn],w[maxn];
int visit[maxn],N,S,P,pre[maxn];
double len[maxn][maxn];//表示点i,j在最小生成树上的最长直径
double c[maxn][maxn];
void init () {
    for (int i=0;i<maxn;i++)
        for (int j=0;j<maxn;j++) 
            g[i][j]=inf,c[i][j]=0,len[i][j]=0;
} 
double prim (int s) {
    fill(d,d+maxn,inf);
    fill(visit,visit+maxn,0);
    for (int i=1;i<=N;i++) pre[i]=i;
    d[s]=0;
    double ans=0;
    for (int i=1;i<=N;i++) {
        int u=-1,min=inf;
        for (int j=1;j<=N;j++) 
            if (!visit[j]&&d[j]<min) {
                u=j;min=d[j];
            }
        if (u==-1) return -1;
        visit[u]=1;
        ans+=d[u];
        if (pre[u]!=u) 
            c[u][pre[u]]=c[pre[u]][u]=1;
        for (int v=1;v<=N;v++) 
            if (!visit[v]&&g[u][v]!=inf&&g[u][v]<d[v]) {
                d[v]=g[u][v];
                pre[v]=u;
            }
        for (int v=1;v<=N;v++) 
            if (visit[v]&&u!=v)
                len[u][v]=len[v][u]=max(len[pre[u]][v],d[u]);
    }
    return ans;
}
struct node {
    double x,y;
}Node[maxn];
int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&N);
        for (int i=1;i<=N;i++) 
            scanf("%lf%lf%lf",&Node[i].x,&Node[i].y,&w[i]);
            init();
            for (int i=1;i<=N;i++) 
                for (int j=i+1;j<=N;j++) 
                    g[i][j]=g[j][i]=sqrt((Node[i].x-Node[j].x)*(Node[i].x-Node[j].x)+
                    (Node[i].y-Node[j].y)*(Node[i].y-Node[j].y));
            double mst=prim(1);
            double Max=0;
            for (int i=1;i<=N;i++)
                for (int j=i+1;j<=N;j++)
                    if (!c[i][j]) 
                        Max=max(Max,(w[i]+w[j])/(mst-len[i][j]));
                    else 
                        Max=max(Max,(w[i]+w[j])/(mst-g[i][j]));
                    printf("%.2f\n",Max);            
    }
}
View Code


E. Just a Hook (line segment tree)

Topic:

At the beginning, the entire sequence is 1, and next, enter l, r, x each time. It means that between l and r is modified to x and x will only be 1, 2, 3, and finally ask you the sum of the sequence.

answer:

Line tree + delay mark, old template title

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
struct node {
    int l,r,sum,lazy;
}segTree[maxn*4];
int N,M;
void build (int i,int l,int r) {
    segTree[i].l=l;
    segTree[i].r=r;
    segTree[i].lazy=0;
    if (l==r) {
        segTree[i].sum=1;
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    segTree[i].sum=segTree[i<<1].sum+segTree[i<<1|1].sum;
}
void spread (int i) {
    if (segTree[i].lazy) {
        segTree[i<<1].sum=segTree[i].lazy*(segTree[i<<1].r-segTree[i<<1].l+1);
        segTree[i<<1|1].sum=segTree[i].lazy*(segTree[i<<1|1].r-segTree[i<<1|1].l+1);
        segTree[i<<1].lazy=segTree[i].lazy;
        segTree[i<<1|1].lazy=segTree[i].lazy;
        segTree[i].lazy=0;
    }
} 
void update (int i,int l,int r,int val) {
    //区间更新
    if (l<=segTree[i].l&&segTree[i].r<=r) {
        segTree[i].sum=val*(segTree[i].r-segTree[i].l+1);
        segTree[i].lazy=val;
        return;
    } 
    spread(i);
    int mid=(segTree[i].l+segTree[i].r)>>1;
    if (l<=mid) 
        update(i<<1,l,r,val);
    if (r>mid)
        update(i<<1|1,l,r,val);
    segTree[i].sum=segTree[i<<1].sum+segTree[i<<1|1].sum;
}
int query (int i,int l,int r) {
    if (l<=segTree[i].l&&r>=segTree[i].r)
        return segTree[i].sum;
    spread(i);
    int mid=(segTree[i].l+segTree[i].r)>>1;
    int ans=0;
    if (l<=mid) 
        ans+=query(i<<1,l,r);
    if (r>mid)
        ans+=query(i<<1|1,l,r);
    return ans; 
}
int T;
int main () {
    scanf("%d",&T);
    for (int k=1;k<=T;k++) {
        scanf("%d%d",&N,&M);
        build(1,1,N);
        for (int i=1;i<=M;i++) {
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            update(1,l,r,x);
        }
        printf("Case %d: The total value of the hook is %d.\n",k,query(1,1,N));
    }
}
View Code

 

FI Hate It (line segment tree)

Topic:

A comparison habit is popular in many schools. Teachers like to ask, from XX to XX, what is the highest score?
This makes many students very disgusted.

Whether you like it or not, what you need to do now is to write a program in accordance with the teacher's request, simulating the teacher's inquiry. Of course, teachers sometimes need to update a student ’s grades.

answer:

Single-point modification of line segment tree + interval query, which is a simple question

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn=2e5+100;
struct node {
    int l,r,sum,lazy;
}segTree[maxn*4];
int a[maxn];
int N,M;
void build (int i,int l,int r) {
    segTree[i].l=l;
    segTree[i].r=r;
    segTree[i].lazy=0;
    if (l==r) {
        segTree[i].sum=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
}
void update (int i,int x,int y) {
    if (segTree[i].l==x&&segTree[i].r==x) {
        segTree[i].sum=y;
        return;
    }
    int mid=(segTree[i].l+segTree[i].r)>>1;
    if (x<=mid) 
        update(i<<1,x,y);
    else 
        update(i<<1|1,x,y);
    segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
}
int query (int i,int l,int r) {
    if (segTree[i].l>=l&&segTree[i].r<=r) {
        return segTree[i].sum;
    } 
    int mid=(segTree[i].l+segTree[i].r)>>1;
    int Max=-1;
    if (l<=mid)
        Max=max(Max,query(i<<1,l,r));
    if (r>mid)
        Max=max(Max,query(i<<1|1,l,r));
    return Max;
}
int main () {
    while (~scanf("%d%d",&N,&M)) {
        for (int i=1;i<=N;i++) scanf("%d",&a[i]);
        build(1,1,N);
        string s;
        int x,y;
        for (int i=1;i<=M;i++) {
            cin>>s>>x>>y;
            if (s=="Q") {
                printf("%d\n",query(1,x,y));
            }
            else {
                update(1,x,y);
            }
        }
    }
}
View Code

 

 G. BillBoard (line segment tree)

Topic:

answer:

It ’s a bit esoteric to put the whole picture upright and make it with a line segment tree. I have n’t fully grasped it and looked at other people ’s solutions ..
 
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6+15;
struct node {
    int l,r,sum;
}segTree[maxn*4];
int h,w,n;
void build (int i,int l,int r) {
    segTree[i].l=l;
    segTree[i].r=r;
    segTree[i].sum=w;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
}
int query (int i,int x) {
    if (segTree[i].l==segTree[i].r) {
        segTree[i].sum-=x;
        return segTree[i].l;
    }
    int mid=(segTree[i].l+segTree[i].r)>>1;
    int ans;
    if (segTree[i<<1].sum>=x)
        ans=query(i<<1,x);
    else 
        ans=query(i<<1|1,x);
    segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
    return ans;
}
int main () {
    while (~scanf("%d%d%d",&h,&w,&n)) {
        h=min(h,n);
        build(1,1,h);
        int x;
        while (n--) {
            scanf("%d",&x);
            if (segTree[1].sum<x) 
                printf("-1\n");
            else 
                printf("%d\n",query(1,x));
        }
    }
}
View Code

 

Guess you like

Origin www.cnblogs.com/algorithmgroup/p/12723165.html