题解 降雷皇
第一问用二分栈做的,直接导致第二问思路僵化
其实所有可行方案数在跑DP的时候就可以顺带求出来
直接用个线段树优化一下就行了,注意当len相等的时候cnt的合并
做第二问的时候思路就很僵,总想着单独做第二问
但其实合并到第一问里更好做
于是那么多人都A了就我60pts就很自闭
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#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, typ;
int a[N];
const ll mod=123456789ll;
namespace force{
ll ans, len;
void dfs(int u, int cnt) {
if (cnt==len) {++ans; return ;}
for (int i=u+1; i<=n; ++i) {
if (a[i]>a[u]) dfs(i, cnt+1);
}
}
void solve(int k) {
len=k;
for (int i=1; i<=n; ++i) dfs(i, 1);
printf("%lld\n", ans);
exit(0);
}
}
namespace task1{
int v[N], top;
ll ans=1, t;
int rot[N];
const int SIZE=N*155;
int tot, tl[SIZE], tr[SIZE], lson[SIZE], rson[SIZE]; ll sum[SIZE];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define l(p) lson[p]
#define r(p) rson[p]
#define sum(p) sum[p]
#define pushup(p) sum(p)=(sum(l(p))+sum(r(p)))%mod
void upd(int& p, int l, int r, int pos, ll dat) {
if (!p) {p=++tot; tl(p)=l; tr(p)=r;}
if (l==r) {sum(p)=(sum(p)+dat)%mod; return ;}
int mid=(l+r)>>1;
if (pos<=mid) upd(l(p), l, mid, pos, dat);
else upd(r(p), mid+1, r, pos, dat);
pushup(p);
}
ll query(int p, int l, int r) {
if (!p) return 0ll;
if (l<=tl(p) && r>=tr(p)) return sum(p);
int mid=(tl(p)+tr(p))>>1; ll ans=0;
if (l<=mid) ans+=query(l(p), l, r), ans%=mod;
if (r>mid) ans+=query(r(p), l, r), ans%=mod;
return ans;
}
void solve() {
//cout<<double(sizeof(tl)*4+sizeof(sum))/1024/1024<<endl;
for (int i=1; i<=n; ++i) {
if (!top || a[i]>v[top]) v[++top]=a[i];
else *lower_bound(v+1, v+top+1, a[i])=a[i];
}
printf("%d\n", top);
//for (int i=1; i<=top; ++i) cout<<v[i]<<' '; cout<<endl;
if (!typ) exit(0);
//force::solve(top);
for (int i=n; i; --i) {
for (int j=top-1; j; --j) {
t = query(rot[j-1], a[i]+1, N);
cout<<i<<' '<<j<<' '<<t<<endl;
if (t) {
upd(rot[j], 1, N, a[i], t);
//cout<<"upd"<<j<<": "<<a[i]<<' '<<t<<endl;
}
}
upd(rot[0], 1, N, a[i], 1); //, cout<<"upd0: "<<a[i]<<endl;
}
printf("%lld\n", sum(rot[top-1]));
exit(0);
}
#undef pushup
}
namespace task{
const int SIZE=N*155;
int tot, tl[SIZE], tr[SIZE];
struct value{ll len, cnt; inline void build(int l, int c) {len=l; cnt=c;} value():len(0),cnt(0){}}val[SIZE];
inline bool operator < (value a, value b) {return a.len<b.len;}
inline bool operator == (value a, value b) {return a.len==b.len;}
inline value operator + (value a, value b) {a.cnt+=b.cnt, a.cnt%=mod; return a;}
inline void operator += (value& a, value b) {a.cnt+=b.cnt, a.cnt%=mod;}
inline value merge(value a, value b) {if (a==b) return a+b; else return max(a, b);}
#define tl(p) tl[p]
#define tr(p) tr[p]
#define val(p) val[p]
inline void pushup(int p) {
if (val(p<<1)==val(p<<1|1)) val(p)=val(p<<1)+val(p<<1|1);
else val(p)=max(val(p<<1), val(p<<1|1));
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int pos, value dat) {
//cout<<"upd "<<p<<' '<<pos<<endl;
if (tl(p)==tr(p)) {if (val(p)==dat) val(p)+=dat; else val(p)=max(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);
}
value query(int p, int l, int r) {
//cout<<"query "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<l<<' '<<r<<endl;
if (l<=tl(p) && r>=tr(p)) return val(p);
int mid=(tl(p)+tr(p))>>1; value ans;
if (l<=mid) ans=merge(ans, query(p<<1, l, r));
if (r>mid) ans=merge(ans, query(p<<1|1, l, r));
//cout<<"return "<<endl;
return ans;
}
void solve() {
value t;
build(1, 1, N);
//cout<<"tot: "<<tot<<endl;
for (int i=1; i<=n; ++i) {
//cout<<i<<endl;
t=query(1, 1, a[i]-1);
//cout<<"return "<<t.len<<' '<<t.cnt<<endl;
++t.len; if (!t.cnt) t.cnt=1;
upd(1, a[i], t); //, cout<<"upd: "<<a[i]<<' '<<t.len<<' '<<t.cnt<<endl;
}
t=query(1, 1, N);
printf("%lld\n", t.len);
if (typ) printf("%lld\n", t.cnt);
exit(0);
}
}
signed main()
{
n=read(); typ=read();
for (int i=1; i<=n; ++i) a[i]=read()+1;
//task1::solve();
task::solve();
return 0;
}