QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#522970 | #5047. Permutation | JEdward | WA | 53ms | 17920kb | C++17 | 5.5kb | 2024-08-17 17:37:13 | 2024-08-17 17:37:14 |
Judging History
answer
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define int long long
#define endl '\n'
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define pb push_back
#define all(s) s.begin(), s.end()
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define here system("pause")
using namespace std;
template <class T> inline void read(T& x) { x = 0; char c = getchar(); bool f = 0; for (; !isdigit(c); c = getchar()) f ^= (c == '-'); for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48); x = f ? -x : x; }
template <class T> inline void write(T x) { if (x < 0) putchar('-'), x = -x; if (x < 10) putchar(x + 48); else write(x / 10), putchar(x % 10 + 48); }
template<typename T> void chkmin(T& lhs, const T& rhs) { lhs = lhs > rhs ? rhs : lhs; }
template<typename T> void chkmax(T& lhs, const T& rhs) { lhs = lhs < rhs ? rhs : lhs; }
const int N = 5e5+5;
const int mod = 998244353;
const int INF = 1e18+7;
const double eps = 1e-6;
inline int pow(int a, int b, int p){ int res = 1%p; while(b){ if(b&1) res=res*a%p; a=a*a%p, b>>=1;} return res;}
inline int inv(int a, int p){ return pow(a,p-2,p)%p;}
mt19937 rnd(chrono::duration_cast< chrono::nanoseconds>(chrono::system_clock::now().time_since_epoch()).count());
inline int randint(int L, int R) {
uniform_int_distribution<int> dist(L, R);
return dist(rnd);
}
//#define LOCAL
int n, c;
int a[N], pos[N];
int J[N];
int tr[N<<2], tag[N<<2];
inline void build(int p, int pl, int pr){
tr[p] = tag[p] = 0;
if(pl==pr) return ;
int mid = pl+pr>>1;
build(ls(p), pl, mid);
build(rs(p), mid+1, pr);
}
inline void push_down(int p, int pl, int pr){
tag[ls(p)] = tag[rs(p)] = 1;
int mid = pl + pr >> 1;
tr[ls(p)] = mid - pl + 1;
tr[rs(p)] = pr - mid;
tag[p] = 0;
}
inline void update(int p, int pl, int pr, int l, int r){
if(l <= pl && pr <= r) {
tr[p] = pr - pl + 1;
tag[p] = 1;
return ;
}
if(tag[p]) push_down(p, pl, pr);
int mid = pl + pr >> 1;
if(l <= mid) update(ls(p), pl, mid, l, r);
if(r > mid) update(rs(p), mid+1, pr, l, r);
tr[p] = tr[ls(p)] + tr[rs(p)];
}
inline int query(int p, int pl, int pr, int l, int r){
if(pl>=l && pr<=r) return tr[p];
if(tag[p]) push_down(p, pl, pr);
int mid = pl+pr>>1, res = 0;
if(r<=mid) res += query(ls(p), pl, mid, l, r);
if(l>mid) res += query(rs(p), mid+1, pr, l, r);
return res;
}
set<int> st;
bool vis[N];
struct node{
int l, r;
}block[N];
int f[N];
inline int find(int x){
return x==f[x] ? x : f[x] = find(f[x]);
}
inline void merge(int x, int y){//把y合并到x里
x = find(x), y = find(y);
f[y] = x;
chkmin(block[x].l, block[y].l);
chkmax(block[x].r, block[y].r);
}
inline void sol(){
cin >> n >> c;
st.clear();
for(int i=1;i<=n;i++){
cin >> a[i];
pos[a[i]] = i;
f[i] = i;
block[i] = {i, i};
vis[i] = 0;
}
// build(1,1,n);//线段树只是用来统计 【段】并上【点】 的覆盖总和
st.insert(0);
st.insert(n+1);
int ans = 1;
for(int i=1;i<=n;i++){
int x = pos[i];
vis[x] = 1;
auto p = st.upper_bound(x);
int L = *prev(p), R = *p;
//先判断在不在【段】里
int anc = find(x);
if(block[anc].l ^ block[anc].r){
//在段里 下一步要扩展merge
int nowl = block[anc].l, nowr = block[anc].r;
if(L >= nowl){
//左边不可能是可扩展的
}else{
int LL = *prev(st.upper_bound(nowl));
if(nowl - c > LL){
for(int j=nowl-c;j<nowl;j++){
merge(anc, j);
}
}else{
for(int j=LL+1;j<nowl;j++){
merge(anc, j);
}
}
}
if(R <= nowr){
//右边不可能是可扩展的
}else{
int RR = *(st.upper_bound(nowr));
if(nowr + c < RR){
for(int j=nowr+1;j<=nowr+c;j++){
merge(anc, j);
}
}else{
for(int j=nowr+1;j<RR;j++){
merge(anc, j);
}
}
}
int ret = 0;
if(x > pos[1]){
for(int j=max(block[anc].l, pos[1]+1);j<=block[anc].r;j++){
if(!vis[j]) ++ret;
}
if(ret) ans = ans * ret % mod;
}else if(x < pos[1]){
for(int j=block[anc].l;j<=min(pos[1]-1, block[anc].r);j++){
if(!vis[j]) ++ret;
}
if(ret) ans = ans * ret % mod;
}
// update(1,1,n,block[anc].l, block[anc].r);
}else{
//不在段里 下一步要扩展merge
if(x - c > L){
for(int j=x-c;j<x;j++){
merge(x, j);
}
}
if(x + c < R){
for(int j=x+1;j<=x+c;j++){
merge(x, j);
}
}
int ret = 0;
if(x > pos[1]){
for(int j=max(block[x].l, pos[1]+1);j<=block[x].r;j++){
if(!vis[j]) ++ret;
}
if(ret) ans = ans * ret % mod;
}else if(x < pos[1]){
for(int j=block[x].l;j<=min(pos[1]-1, block[x].r);j++){
if(!vis[j]) ++ret;
}
if(ret) ans = ans * ret % mod;
}else{
for(int j=block[x].l;j<=block[x].r;j++){
if(!vis[j]) ++ret;
}
if(ret) ans = ans * ret % mod;
}
// update(1,1,n,block[x].l,block[x].r);
}
st.insert(x);
// cout << " " << ans << endl;
// int sum = query(1,1,n,1,n);
}
cout << ans << endl;
}
signed main(){
#ifdef LOCAL
clock_t CLOCK_S = clock();
freopen("1.in", "r", stdin);
#endif
IOS;
J[0] = 1;
for(int i=1;i<N;i++){
J[i] = J[i-1] * i % mod;
}
int tc = 1;
cout << fixed << setprecision(2);
cin >> tc;
while(tc--){
sol();
}
#ifdef LOCAL
clock_t CLOCK_E = clock();
cerr << "Judging Time: " << 1.00 * (CLOCK_E - CLOCK_S) / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}
/*
5 4
1 3 2 5 4
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 17920kb
input:
5 5 3 3 4 2 1 5 5 4 4 2 1 3 5 5 2 4 5 3 1 2 5 3 4 3 2 1 5 5 2 2 3 1 5 4
output:
6 1 4 6 4
result:
ok 5 number(s): "6 1 4 6 4"
Test #2:
score: -100
Wrong Answer
time: 53ms
memory: 15892kb
input:
100000 5 4 1 3 2 5 4 5 3 5 1 4 2 3 5 2 1 4 5 3 2 5 4 5 2 4 3 1 5 4 2 5 4 1 3 5 4 1 2 3 5 4 5 4 4 3 2 5 1 5 3 1 5 4 3 2 5 3 3 2 5 4 1 5 4 4 3 1 5 2 5 4 4 3 5 2 1 5 2 3 2 1 4 5 5 3 2 4 5 1 3 5 3 2 1 4 3 5 5 3 2 1 5 4 3 5 2 2 1 3 4 5 5 4 2 3 1 4 5 5 2 1 2 4 5 3 5 3 2 4 1 5 3 5 3 2 4 3 5 1 5 3 4 1 3 5 2...
output:
24 6 12 24 1 24 24 18 18 1 24 4 6 6 6 4 1 12 1 18 6 24 18 4 18 4 6 18 18 6 4 1 18 18 1 18 24 18 6 1 12 18 6 4 4 24 12 4 24 4 4 24 18 1 1 1 1 6 1 4 1 18 1 18 4 4 6 24 18 4 6 1 12 1 4 4 6 24 18 6 4 18 1 12 6 24 1 4 12 1 1 6 1 1 24 12 18 1 4 18 1 4 24 6 4 24 6 24 1 1 6 1 18 24 1 4 1 1 4 6 1 6 4 18 1 24...
result:
wrong answer 3rd numbers differ - expected: '6', found: '12'