【dp+離散化+線段樹優化】Paint
阿新 • • 發佈:2019-02-11
題意: 求不相交的區間集合,沒有覆蓋到的範圍最小
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 4e5+10; const int M = 26; const int INF = 0x3f3f3f3f; vector<LL> xs; inline int getid(LL x){return lower_bound(xs.begin(),xs.end(), x) - xs.begin() + 1;} struct asd{ LL l,r; LL sum; }a[N]; bool cmp(asd x,asd y){ if(x.l != y.l) return x.l < y.l; return x.r < y.r; } struct Node{ int left,right; LL maxn; }node[N*4]; int father[N*4]; void BulitTree(int i,int l,int r){ node[i].left = l; node[i].right = r; node[i].maxn = 0; if(l == r){ father[l] = i; return ; } BulitTree(i*2,l,(l+r)/2); BulitTree(i*2+1,(l+r)/2+1,r); } void Update(int i){ if(i == 1) return ; int pi = i/2; LL x = node[pi*2].maxn; LL y = node[pi*2+1].maxn; node[pi].maxn = max(x,y); Update(pi); } LL ans; void Query(int i,int l,int r){ if(node[i].right==r && node[i].left==l){ ans = max(ans,node[i].maxn); return ; } i = i*2; if(l <= node[i].right){ if(r <= node[i].right){ Query(i,l,r); } else{ Query(i,l,node[i].right); } } i++; if(r >= node[i].left){ if(l >= node[i].left) Query(i,l,r); else Query(i,node[i].left,r); } } int main(){ LL n; int m; scanf("%lld%d",&n,&m); BulitTree(1,1,m*2+1); for(int i = 1; i <= m; i++){ scanf("%I64d%I64d",&a[i].l,&a[i].r); a[i].sum = a[i].r-a[i].l+1; } sort(a+1,a+m+1,cmp); xs.push_back(0); for(int i = 1; i <= m; i++) { xs.push_back(a[i].l); xs.push_back(a[i].r); } sort(xs.begin(), xs.end()); vector<LL>::iterator e; e=unique(xs.begin(),xs.end()); xs.erase(unique(xs.begin(), xs.end()) , xs.end()); int id = getid(0); int x = father[id]; node[x].maxn = 0; Update(x); for(int i = 1; i <= m; i++){ id = getid(a[i].l); ans = 0; Query(1,1,id-1); id = getid(a[i].r); x = father[id]; node[x].maxn = ans+a[i].sum; Update(x); } ans = 0; Query(1,1,m*2+1); printf("%I64d\n",n-ans); return 0; }