题解 降雷皇

传送门

第一问用二分栈做的,直接导致第二问思路僵化

其实所有可行方案数在跑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;
}
posted @ 2021-07-28 19:08  Administrator-09  阅读(19)  评论(0编辑  收藏  举报