题解 排队
发现就是求 LIS 长度及必须位置集合
考虑求出总方案数后 check 每个点的前,后缀方案数乘积是否等于总方案数
因为总方案数大的离谱所以要取模
然后 ull 自然溢出冲突率接近 \(100\%\) 所以挂成暴力分了
- 判断大数是否相等要对大质数取模!这种情况下自然溢出就是找死
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], b[N];
const ll mod=1e9+7;
namespace force{
int sta[N], buc[N], ans, top;
bool ban[110][110];
vector<int> rec;
void solve() {
for (int i=1; i<=n; ++i) b[a[i]]=i;
for (int i=1; i<=n; ++i) {
for (int j=1; j<n; ++j) if (a[j]>a[j+1]) {
ban[a[j]][a[j+1]]=ban[a[j+1]][a[j]]=1;
swap(a[j], a[j+1]);
}
}
//cout<<"ban: "<<endl; for (int i=1; i<=n; ++i) {for (int j=1; j<=n; ++j) cout<<ban[i][j]<<' '; cout<<endl;}
int lim=1<<n;
for (int s=1,cnt; s<lim; ++s) {
top=0;
for (int i=1; i<=n; ++i) if (s&(1<<(i-1))) sta[++top]=i;
for (int i=1; i<=top; ++i)
for (int j=i+1; j<=top; ++j)
if (ban[sta[i]][sta[j]]) goto jump;
cnt=__builtin_popcount(s);
if (cnt>ans) ans=cnt, rec.clear(), rec.pb(s);
else if (cnt==ans) rec.pb(s);
jump: ;
}
printf("%lld\n", ans);
for (auto s:rec) {for (int i=1; i<=n; ++i) if (s&(1<<(i-1))) ++buc[i];}
for (int i=1; i<=n; ++i) if (buc[i]==rec.size()) printf("%lld ", b[i]);
printf("\n");
}
}
namespace task1{
int sta[N], top;
ll pre[N], f[N];
int tl[N<<2], tr[N<<2];
struct seg{
int val; ll num;
seg():val(0),num(0){}
seg(int a, ll b):val(a),num(b){}
inline seg operator + (seg b) {
seg ans;
ans.val=max(val, b.val);
if (ans.val==val) ans.num+=num;
if (ans.val==b.val) ans.num+=b.num;
ans.num%=mod;
return ans;
}
}val[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define val(p) val[p]
inline void pushup(int p) {val(p)=val(p<<1)+val(p<<1|1);}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) {val(p)={0, 1}; return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void upd(int p, int pos, seg dat) {
if (tl(p)==tr(p)) {val(p)=dat; return ;}
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) upd(p<<1, pos, dat);
else upd(p<<1|1, pos, dat);
pushup(p);
}
seg query(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return val(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid && r>mid) return query(p<<1, l, r)+query(p<<1|1, l, r);
else if (l<=mid) return query(p<<1, l, r);
else return query(p<<1|1, l, r);
}
#define ls(p) lson[p]
#define rs(p) rson[p]
#define sum(p) sum[p]
int lson[N*100], rson[N*100], tot; ll sum[N*100];
struct pst{
int rot=0;
inline void pushup(int p) {sum(p)=(sum(ls(p))+sum(rs(p)))%mod;}
void upd(int& p, int tl, int tr, int pos, ll val) {
if (!p) p=++tot;
if (tl==tr) {sum(p)=val; return ;}
int mid=(tl+tr)>>1;
if (pos<=mid) upd(ls(p), tl, mid, pos, val);
else upd(rs(p), mid+1, tr, pos, val);
pushup(p);
}
ll query(int p, int tl, int tr, int ql, int qr) {
if (!p) return 0;
if (ql<=tl&&qr>=tr) return sum(p);
int mid=(tl+tr)>>1; ll ans=0;
if (ql<=mid) ans+=query(ls(p), tl, mid, ql, qr);
if (qr>mid) ans+=query(rs(p), mid+1, tr, ql, qr);
return ans%mod;
}
void add(int pos, ll val) {upd(rot, 1, n+1, pos, val);}
ll query(int l, int r) {return query(rot, 1, n+1, l, r);}
}suf[N];
void solve() {
//cout<<double(sizeof(sum)*2+sizeof(tl)*2+sizeof(val))/1000/1000<<endl;
build(1, 1, n);
ll max_len=0;
for (int i=1; i<=n; ++i) {
//cout<<"i: "<<i<<endl;
seg t=query(1, 1, a[i]);
upd(1, a[i], {t.val+1, t.num});
//cout<<"num: "<<t.num<<endl;
//if (!t.num) cout<<"i: "<<i<<endl;
max_len=max(max_len, f[i]=t.val+1);
pre[i]=t.num;
}
printf("%lld\n", max_len);
suf[max_len+1].add(n+1, 1);
ll tot=0;
for (int i=1; i<=n; ++i) if (f[i]==max_len) tot=(tot+pre[i])%mod;
//cout<<"tot: "<<tot<<endl;
for (int i=n; i; --i) {
ll tem=suf[f[i]+1].query(a[i], n+1);
if (pre[i]*tem%mod==tot) sta[++top]=i;
suf[f[i]].add(a[i], tem);
}
while (top) printf("%lld ", sta[top--]);
printf("\n");
}
}
signed main()
{
freopen("queue.in", "r", stdin);
freopen("queue.out", "w", stdout);
n=read();
for (int i=1; i<=n; ++i) a[i]=read();
// force::solve();
task1::solve();
return 0;
}