F - Almost Sorted 2
问题陈述
给你一个长度为 NNN 的整数序列 A=(A1,A2,…,AN)A=(A_1,A_2,\ldots,A_N)A=(A1,A2,…,AN) 和一个正整数 DDD 。
求通过重新排列 AAA 得到的满足以下条件的整数序列 B=(B1,B2,…,BN)B=(B_1, B_2, \ldots, B_N)B=(B1,B2,…,BN) 的个数(模为 998244353998244353998244353 ):
- Bi+1≥Bi−DB_{i+1}\geq B_i-DBi+1≥Bi−D 对所有 i (1≤i≤N−1)i\ (1\leq i\leq N-1)i (1≤i≤N−1) 都成立。
考虑插入法,每次按BiB_iBi从小到大插入下一个数,一个数可以被插在某个位置等价于后面那个数≥Bi−D\geq B_i-D≥Bi−D
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define vii(f,n,m) vector<int> f(n,vi(m))
#define pi pair<int,int>
#define SI(a) ((a).size())
#define is_ok(a) puts(a?"Yes":"No")
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os, const Cont& v){
os<<"[";
for(auto& x:v){os<<x<<", ";}
return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os, const pair<Ts...>& p){
return os<<"{"<<p.first<<", "<<p.second<<"}";
}
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
template<int MOD, int RT> struct mint {
static const int mod = MOD;
static constexpr mint rt() { return RT; } // primitive root for FFT
int v; explicit operator int() const { return v; } // explicit -> don't silently convert to int
mint():v(0) {}
mint(ll _v) { v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD);
if (v < 0) v += MOD; }
bool operator==(const mint& o) const {
return v == o.v; }
friend bool operator!=(const mint& a, const mint& b) {
return !(a == b); }
friend bool operator<(const mint& a, const mint& b) {
return a.v < b.v; }
mint& operator+=(const mint& o) {
if ((v += o.v) >= MOD) v -= MOD;
return *this; }
mint& operator-=(const mint& o) {
if ((v -= o.v) < 0) v += MOD;
return *this; }
mint& operator*=(const mint& o) {
v = int((ll)v*o.v%MOD); return *this; }
mint& operator/=(const mint& o) { return (*this) *= inv(o); }
friend mint pow(mint a, ll p) {
mint ans = 1; assert(p >= 0);
for (; p; p /= 2, a *= a) if (p&1) ans *= a;
return ans; }
friend mint inv(const mint& a) { assert(a.v != 0);
return pow(a,MOD-2); }
mint operator-() const { return mint(-v); }
mint& operator++() { return *this += 1; }
mint& operator--() { return *this -= 1; }
friend mint operator+(mint a, const mint& b) { return a += b; }
friend mint operator-(mint a, const mint& b) { return a -= b; }
friend mint operator*(mint a, const mint& b) { return a *= b; }
friend mint operator/(mint a, const mint& b) { return a /= b; }
};
const int MOD=998244353;
using mi = mint<MOD,5>; // 5 is primitive root for both common mods
namespace simp {
vector<mi> fac,ifac,invn;
void check(int x) {
if (fac.empty()) {
fac={mi(1),mi(1)};
ifac={mi(1),mi(1)};
invn={mi(0),mi(1)};
}
while (SI(fac)<=x) {
int n=SI(fac),m=SI(fac)*2;
fac.resize(m);
ifac.resize(m);
invn.resize(m);
for (int i=n;i<m;i++) {
fac[i]=fac[i-1]*mi(i);
invn[i]=mi(MOD-MOD/i)*invn[MOD%i];
ifac[i]=ifac[i-1]*invn[i];
}
}
}
mi gfac(int x) {
assert(x>=0);
check(x); return fac[x];
}
mi ginv(int x) {
assert(x>0);
check(x); return invn[x];
}
mi gifac(int x) {
assert(x>=0);
check(x); return ifac[x];
}
mi binom(int n,int m) {
if (m < 0 || m > n) return mi(0);
return gfac(n)*gifac(m)*gifac(n - m);
}
}
int main()
{
int n=read(),d=read();
vi a(1e6+1,0),s(1e6+1,0);
For(i,n) {
a[read()]++;
}
For(i,1e6) s[i]+=a[i]+s[i-1];
mi ans=1;
For(i,1e6) if(a[i]){
ll k=s[i-1]-((i-d-1>=0)?s[i-d-1]:0)+1;
ll s=a[i];
ans*=simp::binom(k-1+s,s);
}
cout<<ans.v<<endl;
return 0;
}
G - Range Set Modifying Query
问题陈述
有 NNN 个集合 S1,…,SNS_1, \ldots,S_NS1,…,SN 。最初,所有集合都是空的。
你会得到以下格式的 QQQ 个查询。按顺序处理它们。
- 类型 111 :给出的格式为
1 L R x对于满足 L≤i≤RL \leq i \leq RL≤i≤R 的每个 SiS_iSi ,添加 xxx 。 - 类型 222 :指定为
2 L R x为满足 L≤i≤RL \leq i \leq RL≤i≤R 的每个 SiS_iSi ,删除 xxx 。 - 类型 333 :给定为
3 L R求满足 L≤i≤RL \leq i \leq RL≤i≤R 的 SiS_iSi 中元素的最大个数,以及达到这个最大个数的集合的个数。
主席树板子题
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define vii(f,n,m) vector<int> f(n,vi(m))
#define pi pair<int,int>
#define SI(a) ((a).size())
#define is_ok(a) puts(a?"Yes":"No")
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os, const Cont& v){
os<<"[";
for(auto& x:v){os<<x<<", ";}
return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os, const pair<Ts...>& p){
return os<<"{"<<p.first<<", "<<p.second<<"}";
}
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
template<int MOD, int RT> struct mint {
static const int mod = MOD;
static constexpr mint rt() { return RT; } // primitive root for FFT
int v; explicit operator int() const { return v; } // explicit -> don't silently convert to int
mint():v(0) {}
mint(ll _v) { v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD);
if (v < 0) v += MOD; }
bool operator==(const mint& o) const {
return v == o.v; }
friend bool operator!=(const mint& a, const mint& b) {
return !(a == b); }
friend bool operator<(const mint& a, const mint& b) {
return a.v < b.v; }
mint& operator+=(const mint& o) {
if ((v += o.v) >= MOD) v -= MOD;
return *this; }
mint& operator-=(const mint& o) {
if ((v -= o.v) < 0) v += MOD;
return *this; }
mint& operator*=(const mint& o) {
v = int((ll)v*o.v%MOD); return *this; }
mint& operator/=(const mint& o) { return (*this) *= inv(o); }
friend mint pow(mint a, ll p) {
mint ans = 1; assert(p >= 0);
for (; p; p /= 2, a *= a) if (p&1) ans *= a;
return ans; }
friend mint inv(const mint& a) { assert(a.v != 0);
return pow(a,MOD-2); }
mint operator-() const { return mint(-v); }
mint& operator++() { return *this += 1; }
mint& operator--() { return *this -= 1; }
friend mint operator+(mint a, const mint& b) { return a += b; }
friend mint operator-(mint a, const mint& b) { return a -= b; }
friend mint operator*(mint a, const mint& b) { return a *= b; }
friend mint operator/(mint a, const mint& b) { return a /= b; }
};
const int MOD=F;
using mi = mint<MOD,5>; // 5 is primitive root for both common mods
namespace simp {
vector<mi> fac,ifac,invn;
void check(int x) {
if (fac.empty()) {
fac={mi(1),mi(1)};
ifac={mi(1),mi(1)};
invn={mi(0),mi(1)};
}
while (SI(fac)<=x) {
int n=SI(fac),m=SI(fac)*2;
fac.resize(m);
ifac.resize(m);
invn.resize(m);
for (int i=n;i<m;i++) {
fac[i]=fac[i-1]*mi(i);
invn[i]=mi(MOD-MOD/i)*invn[MOD%i];
ifac[i]=ifac[i-1]*invn[i];
}
}
}
mi gfac(int x) {
assert(x>=0);
check(x); return fac[x];
}
mi ginv(int x) {
assert(x>0);
check(x); return invn[x];
}
mi gifac(int x) {
assert(x>=0);
check(x); return ifac[x];
}
mi binom(int n,int m) {
if (m < 0 || m > n) return mi(0);
return gfac(n)*gifac(m)*gifac(n - m);
}
}
int n,q;
struct BIT{
#define MAXN (212345+10)
ll f[MAXN]={};
int n;
void add(int x,ll v) {
for(int i=x;i<=n;i+=i&(-i))
f[i]+=v;
}
ll qur(int x) {
ll v=0;
for(int i=x;i;i-=i&(-i))
v+=f[i];
return v;
}
}T;
namespace Seg{
const int N = MAXN, M = MAXN, LOG2N = 32-__builtin_clz(N-1);
int roots[N+1], allo;
struct Segment { int ch[2], cnt; } seg[N * 4 + M * LOG2N];
void build(int &t, int l, int r) {
t = ++allo;
if (l < r-1) {
int m = l+r >> 1;
build(seg[t].ch[0], l, m);
build(seg[t].ch[1], m, r);
}
}
void add(int *t, int u, int l, int r, int v) {
while (l < r-1) {
*t = ++allo;
seg[*t].cnt = seg[u].cnt+1;
int m = l+r >> 1, d = v >= m;
if (d) l = m;
else r = m;
seg[*t].ch[d^1] = seg[u].ch[d^1];
t = &seg[*t].ch[d];
u = seg[u].ch[d];
}
*t = ++allo;
seg[*t].cnt = seg[u].cnt+1;
}
int kth(int t, int u, int l, int r, int k) {
while (l < r-1) {
int m = l+r >> 1, lcnt = seg[seg[t].ch[0]].cnt-seg[seg[u].ch[0]].cnt, d = k >= lcnt;
if (d) l = m, k -= lcnt;
else r = m;
t = seg[t].ch[d];
u = seg[u].ch[d];
}
return l;
}
int count_less_then_k(int t, int u, int l, int r, int v) {
int ret=0;
while (l < r-1) {
int m = l+r >> 1, lcnt = seg[seg[t].ch[0]].cnt-seg[seg[u].ch[0]].cnt, d = v >= m;
if (d) l = m, ret += lcnt;
else r = m;
t = seg[t].ch[d];
u = seg[u].ch[d];
}
return ret;
}
};
ll a[MAXN];
void work() {
n=read(),q=read();
vector<ll> a(n),u(n),d(n);
Rep(i,n) cin>>a[i];
T.n=n;
Seg::build(Seg::roots[n], 0, n+2);
RepD(i,n-1) {
u[i]=T.qur(n)-T.qur(a[i]);
d[i]=T.qur(a[i]-1);
T.add(a[i],1);
Seg::add(&Seg::roots[i], Seg::roots[i+1], 0, n+2, a[i]);
}
map<int,vi> h;
int id1=-1,id2=-1;
Rep(i,n) {
if(id1==-1 && h.count(a[i])) {
id2=i,id1=h[a[i]][0];
}
if(!h.count(a[i])) {
h[a[i]]={i};
}
else h[a[i]].pb(i);
}
For(i,n-1) {
d[i]+=d[i-1];
u[i]+=u[i-1];
}
while(q--) {
ll k;cin>>k;
if(k<=d[n-1]){
int i;
auto it=lower_bound(ALL(d),k);
if((*it)==k) {
i=lower_bound(ALL(d),k)-d.begin();
}else i=upper_bound(ALL(d),k)-d.begin();
ll newk=k-(i-1>=0?d[i-1]:0);
int j=Seg::kth(Seg::roots[i+1], Seg::roots[n], 0, n+2,newk-1 );
int cnt=Seg::count_less_then_k(Seg::roots[i+1], Seg::roots[n], 0, n+2,j );
auto iter=h[j].end()-(newk-cnt);
cout<<i+1<<' '<<(*iter)+1<<endl;
continue;
}
else if((ll)n*(n-1)/2-k+1<=u[n-1]){
k=(ll)n*(n-1)/2-k+1;
int i;
auto it=lower_bound(ALL(u),k);
if((*it)==k) {
i=lower_bound(ALL(u),k)-u.begin();
}else i=upper_bound(ALL(u),k)-u.begin();
ll newk=k-(i-1>=0?u[i-1]:0);
int j=Seg::kth(Seg::roots[i+1], Seg::roots[n], 0, n+2,(n-i)-newk-1 );
int cnt=n-i-1-Seg::count_less_then_k(Seg::roots[i+1], Seg::roots[n], 0, n+2,j+1 );
auto iter=h[j].end()-(newk-cnt);
cout<<i+1<<' '<<(*iter)+1<<endl;
continue;
}
else cout<<id1+1<<' '<<id2+1<<endl;
}
}
int main()
{
// freopen("g.in","r",stdin);
// freopen(".out","w",stdout);
work();
return 0;
}

569

被折叠的 条评论
为什么被折叠?



