【题解】 UVA1707 【Surveillance】

Seeing that it was a ring, we pulled it into a chain very routinely.

Then we have to enumerate a starting point iii , find at least coveringi + len − 1 i+len-1i+l e n1 The minimum number of line segments that need to be used at this position.

Since each point has to be calculated, you can consider preprocessing multiplication to calculate pi, j p_{i,j}pi,jMeans from iii start with2 j 2^j2The first position that j lines cannot cover. The transfer ispi, j = ppi, j − 1, j − 1 p_{i,j}=p_{p_{i,j-1},j-1}pi,j=ppi,j1,j1

p i , 0 p_{i,0} pi,0That is to cover iiThe maximum right endpoint of the line segment at point i can besetmaintainedwith the idea of ​​difference.

Then enumerate each point, not exceeding i + len − 1 i+len-1i+l e nTry to jump within the range of 1 (similar to the process of seeking LCA), and finally judge whether it can be completely covered.

Code

#include <bits/stdc++.h>
#define MAX 2000005
#define INF 0x3f3f3f3f
using namespace std;

struct node{
    
    
    int l, r;
}a[MAX];
int m, n;
int p[MAX][24];
vector<int> v[MAX];
multiset<int> s;

int main()
{
    
    
    while(cin >> m >> n){
    
    
        memset(p, 0, sizeof(p));
        for(int i = 1; i <= m*2; i++) v[i].clear();
        for(int i = 1; i <= n; i++){
    
    
            scanf("%d%d", &a[i].l, &a[i].r);
            if(a[i].r < a[i].l) a[i].r += m;
            v[a[i].l].push_back(a[i].r);
            v[a[i].r+1].push_back(-a[i].r);
        }
        s.clear();
        for(int i = 1; i <= m*2; i++){
    
    
            for(int x:v[i]){
    
    
                if(x > 0) s.insert(x);
                else s.erase(s.find(-x));
            }
            if(!s.empty()) p[i][0] = *s.rbegin()+1;
            else p[i][0] = i;
        }
        for(int j = 1; j <= 21; j++){
    
    
            for(int i = 1; i <= m*2; i++){
    
    
                p[i][j] = p[p[i][j-1]][j-1];
            }
        }
        int ans = INF;
        for(int i = 1; i <= m; i++){
    
    
            int x = i, t = 0;
            for(int j = 21; j >= 0; j--){
    
    
                if(p[x][j] <= i+m-1) x = p[x][j], t += (1<<j);
            }
            if(p[x][0] > i+m-1) ans = min(ans, t+1);
        }
        if(ans == INF) puts("impossible");
        else cout<<ans<<endl;
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_30115697/article/details/109486163