1293: [SCOI2009]生日禮物
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2800 Solved: 1523
[Submit][Status][Discuss]
Description
小西有一條很長的綵帶,綵帶上掛着各式各樣的彩珠。已知彩珠有N個,分爲K種。簡單的說,可以將綵帶考慮爲x軸,每一個彩珠有一個對應的座標(即位置)。某些座標上可以沒有彩珠,但多個彩珠也可以出現在同一個位置上。 小布生日快到了,於是小西打算剪一段綵帶送給小布。爲了讓禮物綵帶足夠漂亮,小西希望這一段綵帶中能包含所有種類的彩珠。同時,爲了方便,小西希望這段綵帶儘可能短,你能幫助小西計算這個最短的長度麼?綵帶的長度即爲綵帶開始位置到結束位置的位置差。
Input
第一行包含兩個整數N, K,分別表示彩珠的總數以及種類數。接下來K行,每行第一個數爲Ti,表示第i種彩珠的數目。接下來按升序給出Ti個非負整數,爲這Ti個彩珠分別出現的位置。
Output
應包含一行,爲最短綵帶長度。
Sample Input
6 3
1 5
2 1 7
3 1 3 8
1 5
2 1 7
3 1 3 8
Sample Output
3
HINT
有多種方案可選,其中比較短的是1~5和5~8。後者長度爲3最短。
【數據規模】
對於50%的數據, N≤10000;
對於80%的數據, N≤800000;
對於100%的數據,1≤N≤1000000,1≤K≤60,0≤彩珠位置<2^31。
Source
做BZOJ是真的爽啊。。。
對拍造數據能力得到了顯著提升
先把所有位置離散化
狀壓每個位置上的綵球的狀況以及當前區間的綵球的情況
然後尺取法
當滿足條件的時候移動左區間
不滿足移動右區間
就搞出來了
狀壓要用 LL 存結果我用 int 存了卡死我
突然發現好像不要狀壓也能過= =!
不敢嘗試
反正我 A 了。。。。
#include <bits/stdc++.h>
#define pb push_back
#define LL long long
using namespace std;
const int N = 1000010;
vector<int> id;
int ma[N];
int mb[N];
LL cnt[N];
int mc[N];
int getid(int x)
{
return lower_bound(id.begin(), id.end(), x) - id.begin();
}
int main()
{
int n, m;
int len;
int l, r;
LL li;///!!!!
LL now;///!!!
int ans;
int be;
while(scanf("%d%d", &n, &m) == 2){
ans = 0x3f3f3f3f;
be = 0;
memset(cnt, 0, sizeof(cnt));
memset(mc, 0, sizeof(mc));
for(int i = 0; i < m; i ++){
scanf("%d", &mb[i]);
for(int j = 0; j < mb[i]; j ++){
scanf("%d", &ma[be + j]);
id.pb(ma[be + j]);
}
be += mb[i];
}
sort(id.begin(), id.end());
id.erase(unique(id.begin(), id.end()), id.end());
len = id.size();
be = 0;
for(int i = 0; i < m; i ++){
for(int j = 0; j < mb[i]; j ++){
cnt[getid(ma[be + j])] += (1ll * 1 << i);
}
be += mb[i];
}
li = (1ll * 1 << m) - 1;
now = 0;
l = 0;
r = -1;
while(l < len){
if(r == len && now != li){
break;
}
if(now == li){
LL t = cnt[l];
int num = 0;
ans = min(ans, id[r] - id[l]);
while(t){
if(t & 1){
mc[num] --;
if(!mc[num]){
now -= (1ll * 1 << num);
}
}
t >>= 1;
num ++;
}
l ++;
}
else{
LL t;
int num;
r ++;
t = cnt[r];
num = 0;
while(t){
if(t & 1){
mc[num] ++;
if(mc[num] == 1){
now += (1ll * 1 << num);
}
}
t >>= 1;
num ++;
}
}
}
printf("%d\n", ans);
}
return 0;
}