More than 2019 cattle off summer school camp (Session 8) EI

E Explorer

Meaning of the questions: given an undirected graph, each side has a number of upper and lower limits by a group of people to come together n dots from point 1, to go with this group of people can not be separated, the number of these people ask how many can meet the conditions.

Solution: do not dereference problem https://blog.csdn.net/qq_41955236/article/details/99229810 the big brother, speaks good giant. After the interval is simply the original discrete (note discretized to be a special skill, ① the right end of the original interval represents the interval of the original + 1② discretized [l, r-1], ③ this time discretization each point represents the point of the point section to the right of a point, i.e. the point that the contribution of r [i + 1] -l [ i]). ) The discretized segment index build a tree, and on the side of the picture are inserted into the respective nodes interval (e.g., [1,3] is inserted into this edge [2] [3, 4] The two nodes). Then partition the tree line segment to meet the requirements of section to find the answer, specifically, this step is the addition from the constant downward partition with the start of the current point able to save edges to the diagram, if at this time of Figure 1 to n statistics answer partition communication stop, otherwise continue to divide and conquer until connectivity or leaf node.

How to determine the side of the partition while communicating it? As used herein and techniques set determining communication check, from the down side to the plus side of the two end points in the combined set of disjoint-set, and if n is 1 and is in communication with the sets. Note that the backtracking set time is then reduced and the investigation, and because there are backtracking operation, disjoint-set path can not be compressed using a heuristic merge.

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long LL;
int n,m,fa[N],sz[N];
LL ans;
struct edge{
    int u,v,l,r;
}e[N];

int getfa(int x) { return x==fa[x] ? x : getfa(fa[x]); }

vector<int> tree[N<<2],b;
void update(int rt,int l,int r,int ql,int qr,int id) {
    if (ql<=l && r<=qr) {
        tree[rt].push_back(id);
        return;
    }
    int mid=(l+r)>>1;
    if (ql<=mid) update(rt<<1,l,mid,ql,qr,id);
    if (qr>mid) update(rt<<1|1,mid+1,r,ql,qr,id);
} 

void dfs(int rt,int l,int r) {
    vector<int> rec; rec.clear();
    int mid=(l+r)>>1;
     For ( int I = 0 ; I <Tree [RT] .size (); I ++ ) {
         int X = E [Tree [RT] [I]] U, Y =. E [Tree [RT] [I]] .v;
         int FX = getfa (X), FY = getfa (Y);
         IF (SZ [FX]> SZ [FY]) the swap (FX, FY); 
        rec.push_back (FX); 
        FA [FX] = FA [FY]; SZ [FY] + = SZ [FX]; 
    } 
    IF (getfa ( . 1 ) == getfa (n-)) ANS = B + [R & lt] -b [L- . 1 ];   // each point represents the the point is a point to the right of the interval values 
    the else  IF (L <R & lt) DFS (RT << . 1 , L, MID), DFS (RT << . 1 | . 1,mid+1,r);
    for (int i=0;i<rec.size();i++) fa[rec[i]]=rec[i];
}

int main()
{
    cin>>n>>m;
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].l,&e[i].r);
        b.push_back(e[i].l); b.push_back(e[i].r+1);  //右端点+1 
    }    
    sort(b.begin(),b.end());
    b.erase(unique(b.begin(),b.end()),b.end());
    for (int i=1;i<=m;i++) {
        int l=lower_bound(b.begin(),b.end(),e[i].l)-b.begin()+1;
        int r=lower_bound(b.begin(),b.end(),e[i].r+1)-b.begin()+1;
        update(1,1,b.size(),l,r-1,i);  //原区间离散化后是[l,r-1] 
    }
    
    for (int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
    dfs(1,1,b.size());
    cout<<ans<<endl; 
    return 0;
} 
View Code

 

D Distance

The meaning of problems: on a n * m * h (n * m * h <= 1e5) a three-dimensional plane, there are two operation, to make a mark one operation at some point, is two interrogation operation from a point nearest the output from the tag.

Solution: When the game had written a KD-tree decisive TLE. After the game we know that positive solutions are regularly reconstruction.

Specifically: First, we define an array dis point is that all operations run as the starting point of the minimum distance bfs get in on the map. So we will start with a queue v the marking operation hoard up when marking the operation of the queue reaches sqrt (n * m * h) when the queue of all the elements (there sqrt (n * m * h) a) as a starting point to run a bfs to update dis array, not reached sqrt (nmh) months when he first matter to hoard. Then ask how to deal with it? Ask for a answer ans its first equal dis [x] [y] [z], which is represented already ran bfs of points on the graph (Tun has good points) answer, then there is still in the store queue v the point is direct violence update, because at this point does not exceed the queue v sqrt (nmh), which are also not too slow.

Regular Reconstruction - a bit like a block, just to block the operation rather than block the data block that.

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int dx[]={-1,1,0,0,0,0};
const int dy[]={0,0,-1,1,0,0};
const int dz[]={0,0,0,0,-1,1};
struct dat{ int x,y,z; };
int n,m,h,T,dis[N];
vector<dat> v;

int id(int x,int y,int z) { return (x-1)*m*h+(y-1)*h+z; }

queue<dat> q;
void bfs() {
    while (!q.empty()) q.pop();
    for (int i=0;i<v.size();i++) {
        q.push((dat){v[i].x,v[i].y,v[i].z});
        dis[id(v[i].x,v[i].y,v[i].z)]=0;
    }
    while (!q.empty()) {
        dat u=q.front(); q.pop();
        for (int i=0;i<6;i++) {
            int nx=u.x+dx[i],ny=u.y+dy[i],nz=u.z+dz[i];
            if (nx<1 || nx>n || ny<1 || ny>m || nz<1 || nz>h) continue;
            if (dis[id(nx,ny,nz)]>dis[id(u.x,u.y,u.z)]+1) {
                dis[id(nx,ny,nz)]=dis[id(u.x,u.y,u.z)]+1;
                q.push((dat){nx,ny,nz});
            }
        }
    }
}

int main()
{
    cin>>n>>m>>h>>T;
    int k=(int)sqrt(n*m*h);
    memset(dis,0x3f,sizeof(dis));
    while (T--) {
        int opt,x,y,z; scanf("%d%d%d%d",&opt,&x,&y,&z);
        if (opt==1) {
            v.push_back((dat){x,y,z});
            if (v.size()>=k) {  //定期重构 
                bfs();
                v.clear();
            }
        } else {
            int ans=dis[id(x,y,z)];
            for (int i=0;i<v.size();i++)
                ans=min(ans,abs(x-v[i].x)+abs(y-v[i].y)+abs(z-v[i].z));
            printf("%d\n",ans);    
        }
    }
    return 0;
}
View Code

There is also a way of thinking on the more "violence" solution: establish three sub-eight kinds of circumstances BIT check the nearest point pair. This approach is not difficult to understand, in fact, is the case of the absolute value of the sub-character symbols removed.

But the way to achieve it may have more skills, the first is what kind of data structure to store n * m * h <D BIT = 1e5's? Here in two ways: The first is common through the three-dimensional map made into a one-dimensional array, the second is to achieve the triple vector variable-length three-dimensional array. Then the next trick is how to quickly discuss eight kinds of circumstances, there is a more clever way to determine the x / y / z positive and negative to bits by 0-7, but also 0-7 with a binary decision query x / yz the first half or the second half.

The price is almost plagiarism (reader's thing. Ahem) https://www.cnblogs.com/Cwolf9/p/11333344.html the big brother.

#include <bits / STDC ++ H.>
 the using  namespace STD; 
typedef Vector < int > Vl; 
typedef Vector <Vl> VVI; 
typedef Vector <VVI> VVVI;
 const  int INF = 0x3f3f3f3f ;
 int n-, m, H, T; 

struct {the BIT
     int n-, m, H; 
    VVVI 'bit; 
    void the init ( int _n, int _M, int _H) {   // initialization good size can be used directly as a three-dimensional array using 
        n-_n =; m = _M; H = _H; 
        'bit = VVVI (n-+ . 1,VVI(m+1,VI(h+1,INF)));
    }
    void update(int x,int y,int z,int v) {
        for (int i=x;i<=n;i+=i&-i) 
            for (int j=y;j<=m;j+=j&-j)
                for (int k=z;k<=h;k+=k&-k)
                    bit[i][j][k]=min(bit[i][j][k],v);
    }
    int query(int x,int y,int z) {
        int ret=INF;
        for (int i=x;i;i-=i&-i)
            for (int j=y;j;j-=j&-j)
                for (int k=z;k;k-=k&-k)
                    ret=min(ret,bit[i][j][k]);
        return ret;            
    }
}bit[8];

int main()
{
    cin>>n>>m>>h>>T;
    for (int i=0;i<8;i++) bit[i].init(n,m,h);  //这里很重要 
    while (T--) {
        int opt,x,y,z; scanf("%d%d%d%d",&opt,&x,&y,&z);
        if (opt==1) {
            for (int i=0;i<8;i++) {
                int v=((i&1)?x:-x)+(((i>>1)&1)?y:-y)+(((i>>2)&1)?z:-z);
                bit[i].update((i&1)?n+1-x:x,((i>>1)&1)?m+1-y:y,((i>>2)&1)?h+1-z:z,v);            
            }
        } else {
            int ans=INF; 
            for (int i=0;i<8;i++) {
                int v=((i&1)?x:-x)+(((i>>1)&1)?y:-y)+(((i>>2)&1)?z:-z);
                int tmp=bit[i].query((i&1)?n+1-x:x,((i>>1)&1)?m+1-y:y,((i>>2)&1)?h+1-z:z);
                ans=min(ans,-v+tmp);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/clno1/p/11469830.html