題意:給你一段長度為n的序列判斷是否為k-bag的子串行,定義k-bag為k個數的全排列
思路:這題的思路有很多,有hash+map,有dp,也有差分。說一下差分把,首先對與這段序列,有開頭一定在1~min(k,n)之間,用乙個陣列維護這段區間,如果這個陣列t[i]的字首和等於0,那麼就表示這個位置可以作為開頭,反之則不能,基於這個結論,對兩個相同的數字之間的的距離進行分類,如果兩個數字之間的距離》=k,即表示1~k都是可以作為開頭的,如果小於k,那麼就表示這個區間必有乙個位置為開頭,如果 這個序列的 第乙個區間開頭是 x1,那麼後面的區間開頭一定是 x1+y*k,y是乙個整數,那麼 我只要把當前開頭 % k 就可以得到第一區間的開頭,這個值可以加到第乙個區間開頭。這個區間值 +1 的操作可以用差分陣列維護
具體**如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
typedef
long
long ll;
typedef
unsigned
long
long ull;
typedef pair<
int,
int> pii;
#define rep(i, a, n) for(int i = a; i <= n; i++)
#define per(i, a, n) for(int i = n; i >= a; i--)
#define ios std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
#define pi 3.14159265358979323846
const
int inf =
1e9;
const ll onf =
1e18
;const
int maxn =
5e5+10;
inline
intread()
while
(isdigit
(ch)
)return x*f;
}int t[maxn]
, a[maxn]
, ord[maxn]
;bool
cmp(
int x,
int y)
inline
boolcf(
)if(!flag)
return0;
for(
int i =
1; i <= n; i++
) ord[i]
=i;stable_sort
(ord+
1, ord+n+
1, cmp)
;int sz =
min(n, k)
;for
(int i =
1; i <= sz; i++
) t[i]=0
;for
(int i =
2; i <= n; i++)}
for(
int i =
1; i <= sz; i++
)return0;
}signed
main()
else
puts
("no");
}return0;
}
2020暑期牛客第六場 K Bag(思維,字首)
收穫 對於乙個長度為k的區間是否存在 l,l k 1 l,l k 1 l,l k 1 的所有數字,可以用區間和和區間異或和來判別。思路 對於前後殘缺的區間可以預處理出前字尾中不同數字的個數,然後列舉分割點,對於完整的區間用區間和和區間異或和判斷。ll a n xor n sum n ll n,k,s...
牛客多校第六場 K Bag(暴力,貪心)
題意 原序列是一堆k個數全排列組成的。給你乙個串,求這個子串是否可能是原序列子串 思路 直接暴力啊,維護出dp i dp i dp i 代表i ii i k 1i k 1 i k 1是否是全排列,然後列舉第乙個排列的終止位置。列舉起始排列的複雜度為k kk,check的複雜度為n k n kn k,...
牛客多校第六場
d 題意感覺說的不是很清楚,一開始題意弄錯了,以為是最優的方案,結果是對於每個盒子這個 so clever 的人的做法是優先選擇盡可能大的物品裝完乙個盒子,我就不知道這個人 聰明了。思路 賽後知道題意後,5分鐘寫完,瞎暴力就一發過了,我自己都有點出乎意料真水了。includeusing namesp...