題意:給出n個區間,求選擇一些區間,使得乙個點被覆蓋的次數超過m次,最小的花費。花費指的是選擇的區間中最大長度減去最小長度。
座標值這麼大,n比較小,顯然需要離散化,需要乙個技巧,把區間轉化為半開半閉區間,然後線段樹的每乙個節點表示乙個半開半閉區間。
接著我們注意到需要求最小的花費,且這個花費只與選擇的區間集合中的最大長度和最小長度有關。
這意味著如果最大長度和最小長度一定,我們顯然是需要把中間長度的區間盡量的選擇進去使答案不會變的更劣。
不妨把區間按長度排序,列舉每個最小長度區間,然後最大區間盡量的往右移,直到滿足有乙個點覆蓋次數》=m。
這不就是尺取法嗎。。。所以我們需要維護乙個資料結構支援區間加減法,區間查詢最大值。顯然線段樹可以滿足這個要求。
因此總的時間複雜度就是o(nlogn).
# include # includeview code# include
# include
# include
# include
# include
# include
# include
# include
# include
using
namespace
std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0
)# define eps 1e-7
# define mod
1024523
# define inf
1000000000
# define mem(a,b) memset(a,b,
sizeof
(a))
# define for(i,a,n)
for(int i=a; i<=n; ++i)
# define fo(i,a,n)
for(int i=a; ii)
# define bug puts("h
");# define lch p
<<1
,l,mid
# define rch p
<<1|1,mid+1
,r# define mp make_pair
# define pb push_back
typedef pair
pii;
typedef vector
vi;# pragma comment(linker,
"/stack:1024000000,1024000000")
typedef
long
long
ll;int
scan()
while(ch>='
0'&&ch<='9')
return x*f;
}void out(int
a)
if(a>=10) out(a/10
); putchar(a%10+'0'
);}const
int n=500005;//
code begin...
int seg[n<<4], tag[n<<4
];struct nodenode[n];
vi v;
bool comp(node a, node b)
void push_up(int p)
void push_down(int
p)void update(int p, int l, int r, int l, int r, int
val)
}int query(int p, int l, int r, int l, int
r)int
main ()
++r; l=lower_bound(v.begin(),v.begin()+siz,node[r].l)-v.begin()+1
; r=lower_bound(v.begin(),v.begin()+siz,node[r].r+1)-v.begin();
update(
1,1,siz,l,r,1
); }
l=lower_bound(v.begin(),v.begin()+siz,node[l].l)-v.begin()+1
; r=lower_bound(v.begin(),v.begin()+siz,node[l].r+1)-v.begin();
update(
1,1,siz,l,r,-1); ++l;
}if (ans==inf) puts("-1"
);
else printf("
%d\n
",ans);
return0;
}
NOI2016 區間 題解(線段樹 尺取法)
題目鏈結 題目大意 給定 n 個區間 l i,r i 選出 m 個區間使它們有乙個共同的位置 x 且使它們產生的費用最小。求最小費用。費用定義為最長的區間長度減去最短區間長度。因為區間順序改動又不影響答案,我們不妨按照長度排個序。看到資料範圍果斷離散化。思考一種最樸素的做法 將排好序的區間逐一加入數...
luogu P1712區間 題解
noi2016 區間 在數軸上有nn 個閉區間 l 1,r 1 l 2,r 2 l n,r n l1 r1 l2 r2 ln rn 現在要從中選出mm個區間,使得這mm 個區間共同包含至少乙個位置。換句話說,就是使得存在乙個 xx 使得對於每乙個被選中的區間 l i,r i li ri 都有 l i...
線段樹(2)區間修改
快速序列操作i,給出乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構支援一下兩種操作 set l,r,v 把al,al 1,ar的值全部修改為v v 0 query l,r 計算子串行al,al 1,ar的元素和 最小值和最大值。include include using namesp...