QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#222808 | #5047. Permutation | absinthe | WA | 42ms | 3836kb | C++23 | 4.1kb | 2023-10-21 18:52:47 | 2023-10-21 18:52:48 |
Judging History
answer
// problem-url: https://qoj.ac/contest/1039/problem/5047
#if not LOCAL
#define NDEBUG 1
#endif
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(auto i = a; i < (b); ++i)
#define down(x, a) for (auto x = a; x--;)
#define all(x) begin(x), end(x)
#define sz(x) int(size(x))
#define let auto const
using ll = long long;
using lint = ll;
using pii = pair<int, int>;
using vi = vector<int>;
let mod=998244353;
// { ==== Begin library /home/user202729/icpc-trd/content/number-theory/ModularArithmetic.h ====
/**
* Author: user202729
* Date: 2023-10-09
* License: CC0
* Source: folklore
* Status: not tested very well
* Description: Operators for modular arithmetic. You need to set {\tt mod} to
* some number first and then you can use the structure.
*/
// { ==== Begin library euclid.h ====
/**
* Author: Unknown
* Date: 2002-09-15
* Source: predates tinyKACTL
* Description: Finds two integers $x$ and $y$, such that $ax+by=\gcd(a,b)$. If
* you just need gcd, use the built in \texttt{\_\_gcd} instead.
* If $a$ and $b$ are coprime, then $x$ is the inverse of $a \pmod{b}$.
*/
ll euclid(ll a, ll b, ll &x, ll &y) {
if (!b) return x = 1, y = 0, a;
ll d = euclid(b, a % b, y, x);
return y -= a/b * x, d;
}
// } ==== End library euclid.h ====
struct Mod {
int x;
Mod(int y=0) : x(y%mod) { if(x<0) x+=mod; }
static Mod raw(int y){ Mod r; r.x=y; return r; }
void operator+=(Mod b) { if((x+=b.x)>=mod) x-=mod; }
void operator-=(Mod b) { if((x-=b.x)<0) x+=mod; }
Mod operator-() const { return 0-*this; }
void operator*=(Mod b) { x=int(ll(x) * b.x % mod); }
explicit operator int() const{return x;}
[[nodiscard]] Mod pow(auto p) const {
assert(p>=0);
Mod a=*this;
Mod ans = 1; for (; p; p >>= 1, a *= a) if (p&1) ans *= a;
return ans;
}
[[nodiscard]] Mod inv() const {
assert(x!=0);
return pow(mod-2);
//ll z, y, g = euclid(mod, x, z, y); assert(g == 1); return int(y);
}
void operator/=(Mod b) { *this *= b.inv(); }
#define A(O) [[nodiscard]] friend Mod operator O(Mod a, Mod b) { a O##= b; return a; }
A(+) A(-) A(*) A(/)
#undef A
#define C(O) [[nodiscard]] bool operator O(Mod b) const { return x O b.x; }
C(==) C(!=) C(<) C(>) C(<=) C(>=)
#undef C
};
// } ==== End library /home/user202729/icpc-trd/content/number-theory/ModularArithmetic.h ====
int main() {
cin.tie(0)->sync_with_stdio(0);
cin.exceptions(cin.failbit);
int t; cin>>t;
down(_, t){
int n; cin>>n;
int c; cin>>c;
vector<int> pos(n);
rep(i, 0, n){
int val; cin>>val; --val;
pos[val]=i;
}
struct Block{
int rightEnd, leftExtent, leftVal, rightExtent, rightVal;
};
map<int, Block> ranges;
ranges.insert({0, {n, 0, -1, n, -1}});
vector<int> par(n, -1);
vector<int> len(n);
rep(val, 0, n){
let p=pos[val];
let iter=--ranges.upper_bound(p);
auto& [leftEnd, block]=*iter;
auto& [rightEnd, leftExtent, leftVal, rightExtent, rightVal]=block;
assert(p<rightEnd);
assert(leftEnd<=leftExtent);
assert(leftExtent<=rightExtent);
assert(rightExtent<=rightEnd);
int left=p, right=p+1;
down(_, 2){
if(leftExtent!=0 and left-leftExtent<c and leftEnd+(leftEnd==0)+c<=n) left=leftEnd, right=max(right, min(rightEnd, leftExtent+c));
if(rightExtent!=n and rightExtent-right<c and rightEnd-(rightEnd==n)-c>=0) right=rightEnd, left=min(left, max(leftEnd, rightExtent-c));
}
if(left==leftEnd){
assert(right>=leftExtent);
if(leftVal>=0) par[leftVal]=val;
leftVal=val, leftExtent=right;
if(right==rightEnd){
if(rightVal>=0) par[rightVal]=val;
rightVal=-1, rightExtent=rightEnd;
}
}else if(right==rightEnd){
assert(left<=rightExtent);
if(rightVal>=0) par[rightVal]=val;
rightVal=val, rightExtent=left;
assert(left!=leftEnd);
}else{
let oldRightEnd=rightEnd;
rightExtent=rightEnd=p;
ranges.insert(iter, {p+1, {oldRightEnd, p+1, -1, oldRightEnd, -1}});
}
len[val]=right-left;
//assert(cerr<<val<<":"<<left<<' '<<right<<'\n');
}
vector<int> used(n);
Mod answer=1;
rep(val, 0, n){
answer*=len[val]-used[val];
if(par[val]>=0) used[par[val]]+=used[val]+1;
}
cout<<int(answer)<<'\n';
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3836kb
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: 42ms
memory: 3640kb
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 6 24 2 24 24 6 18 1 24 4 6 6 6 4 1 12 1 6 6 24 18 2 18 4 6 6 18 6 4 1 6 18 1 6 24 18 6 1 12 18 6 4 2 24 12 4 24 4 4 24 6 1 0 0 1 6 1 4 1 18 1 18 4 4 6 24 6 4 6 1 12 2 4 4 6 24 18 6 2 6 1 12 6 24 2 4 6 1 1 6 0 1 24 12 18 1 4 18 1 4 24 6 4 24 6 24 0 2 6 1 18 24 1 4 1 1 2 6 1 6 4 18 1 24 6 6 4 24 ...
result:
wrong answer 5th numbers differ - expected: '1', found: '2'