题解 排队

传送门

发现就是求 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;
}
posted @ 2022-02-21 18:05  Administrator-09  阅读(1)  评论(0编辑  收藏  举报