20220504

私货:今天打 GSL 决赛,虽然我也很想让 Creator 赢,但 Rogue 的决赛准备真的太好了,奶一口 Rogue 4:1 夺冠


  • tot 100 (175)
  • rk 8/22

路人女主

0pt, max = 100pts

暴力没写完,赛后写完发现 T 了/kk 算复杂度的时候注意多测

\(s_{i}s_{i+1},t_{i}t_{i+1}\) 中一定有相同字符,因此 \(s,t\) 的 LCS 至少为 \(n\)可以发现合法的串只有两类:

  1. \(s=ababa\cdots,t_{2i+1}=c,t_{2i}=a\text{ or }b\)
  2. \(s_{2i}=t_{2i}=a,\exists k\)\(s\) 的前 \(k\) 个奇数位置为 \(b\),后面为 \(c\)\(t\) 相反

可以归纳证明,非常繁琐,看官方题解吧。可能更靠谱的做法是打表

注意去重:\(aba,cac\) 同时属于第一类和第二类,被算了两遍;\(aba,cbc\) 在第一类中被 \(s,t\)\(t,s\) 各算了一遍,总共三遍

code
const int N = 2e6+5;
int n,m;
LL ans,pw[N];
char s[N],t[N];

bool eq(char x,char y) { return x=='?' || x==y; }
void cal1(char *s,char *t,char a,char b,char c) {
	int cnt = 0;
	for(int i = 1; i <= m; i += 2) if( !eq(s[i],a) || !eq(t[i],c) ) return;
	for(int i = 2; i <= m; i += 2) {
		if( !eq(s[i],b) || t[i] == c ) return;
		cnt += t[i]=='?';
	}
	ans += pw[cnt];
}
void cal2(char a,char b,char c) {
	int cnt = 0;
	for(int i = 2; i <= m; i += 2) if( !eq(s[i],a) || !eq(t[i],a) ) return;
	for(int i = 1; i <= m; i += 2) cnt += eq(s[i],b) + eq(t[i],c);
	ans -= cnt==2*(n+1);
	for(int i = 1; i < m; i += 2)
		cnt += eq(s[i],c)-eq(s[i],b) + eq(t[i],b)-eq(t[i],c),
		ans += cnt==2*(n+1);
}

void MAIN() {
	io>>n>>s+1>>t+1, m = 2*n+1;
	auto slv=[](char a,char b,char c)
		{ cal1(s,t,a,b,c), cal1(t,s,a,b,c), cal2(a,b,c); };
	slv('A','B','C'), slv('A','C','B'), slv('B','A','C'),
	slv('B','C','A'), slv('C','A','B'), slv('C','B','A');
	io<<Mod(ans%mod)<<endl;
} signed main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout);
	pw[0] = 1; Rep(i,1,N) pw[i] = pw[i-1] * 2 %mod;
	int t; io>>t; while( t-- ) ans = 0, MAIN();
	return 0;
}

铃原露露

100pts

做了一整场。思考时断时续,坚信做法没问题因此一直在刚,最后 15min 才写完,运气很好没怎么调。其实思路很顺,代码又全是板子,最慢应该 2.5h 过掉的

考场代码
const int N = 2e5+5;
int n,m,a[N],fa[N],siz[N],le[N],ri[N],pre[N],suf[N];
LL ans[N];
Vi e[N],c[N];
vector<Pii> q[N],b[N];
set<int> s[N];

#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct Seg {
	int t[N*4];
	Seg() { memset(t,0x3f,sizeof t); }
	void mdf(int ql,int qr,int x,int u=1,int l=1,int r=n) {
		if( qr < l || r < ql ) return;
		if( ql <= l && r <= qr ) return ckmin(t[u],x), void();
		mdf(ql,qr,x,ls,l,mid), mdf(ql,qr,x,rs,mid+1,r);
	}
	void dfs(int x,int *a,int u=1,int l=1,int r=n) {
		ckmin(x,t[u]);
		if( l == r ) return a[l] = x, void();
		dfs(x,a,ls,l,mid), dfs(x,a,rs,mid+1,r);
	}
} t1,t2;

void dfs(int u) {
	int son = 0; siz[u] = 1;
	for(int v : e[u]) { dfs(v), siz[u] += siz[v]; if( siz[v] > siz[son] ) son = v; }
	if( son ) {
		swap(s[u],s[son]);
		for(int v : e[u]) if( v != son ) {
			for(int x : s[v]) {
				auto add=[&](int x,int y) {
					if( a[u] < x ) t1.mdf(a[u]+1,x,y);
					else if( y < a[u] ) t2.mdf(y,a[u]-1,-x);
				};
				auto it = s[u].lwb(x);
				if( it != s[u].end() ) add(x,*it);
				if( it != s[u].begin() ) add(*--it,x);
			}
			s[u].insert(all(s[v]));
		}
	}
	s[u].emplace(a[u]);
}

struct {
	LL t1[N],t2[N];
	void add(int p,int x) { for(int i=p;i<=n;i+=i&-i) t1[i] += x, t2[i] += p*x; }
	void add(int l,int r,int x) { add(l,x), add(r+1,-x); }
	LL sum(int p) {
		LL res = 0;
		for(int i=p;i;i-=i&-i) res += (p+1)*t1[i] - t2[i];
		return res;
	}
	LL sum(int l,int r) { return sum(r) - sum(l-1); }
} bit;

#define ls (u<<1)
#define rs (u<<1|1)
#define mid (l+r>>1)
struct {
	struct { int sum,cnt; LL res; } t[N*4];
	void down(int u,int x) { t[u].res += (LL)x * t[u].sum, t[u].cnt += x; }
	void down(int u) { down(ls,t[u].cnt), down(rs,t[u].cnt), t[u].cnt = 0; }
	void ins(int p,int u=1,int l=1,int r=n) {
		++t[u].sum;
		if( l == r ) return;
		down(u), p<=mid ? ins(p,ls,l,mid) : ins(p,rs,mid+1,r);
	}
	void add(int qr,int u=1,int l=1,int r=n) {
		if( qr < l ) return;
		if( r <= qr ) return down(u,1);
		down(u), add(qr,ls,l,mid), add(qr,rs,mid+1,r),
		t[u].res = t[ls].res + t[rs].res;
	}
	LL sum(int ql,int qr,int u=1,int l=1,int r=n) {
		if( qr < l || r < ql ) return 0;
		if( ql <= l && r <= qr ) return t[u].res;
		return down(u), sum(ql,qr,ls,l,mid) + sum(ql,qr,rs,mid+1,r);
	}
} seg;

signed main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout);
	io>>n>>m; For(i,1,n) io>>a[i]; For(i,2,n) io>>fa[i], e[fa[i]].pb(i);
	For(i,1,m) io>>le[i]>>ri[i], q[le[i]-1].pb(i,-1), q[ri[i]].pb(i,1);
	dfs(1), t1.dfs(n+1,suf), t2.dfs(0,pre); For(i,1,n) pre[i] = -pre[i];
	For(i,1,n) {
		if( suf[i] <= n ) b[i].pb(suf[i],n), c[suf[i]].pb(i);
		if( 1 <= pre[i] ) b[i].pb(1,pre[i]);
	}
	For(i,1,n) {
		for(auto j : b[i]) bit.add(j.fi,j.se,1);
		for(auto j : q[i]) ans[j.fi] += j.se * bit.sum(le[j.fi],ri[j.fi]);
	}
	For(i,1,n) {
		for(int j : c[i]) seg.ins(j);
		seg.add(pre[i]);
		for(auto j : q[i]) ans[j.fi] -= j.se * seg.sum(le[j.fi],ri[j.fi]);
	}
	auto cal=[](LL n) { return n * (n-1) / 2 + n; };
	For(i,1,m) io<<cal(ri[i]-le[i]+1)-ans[i]<<endl;
	return 0;
}

赫露艾斯塔

0pt, max = 50pts

6s,\(O(n^{3})\) 完全能过 \(10^3\)。赛时应该写这题暴力的,不过马后炮并没有意义

考虑分类讨论 \(-\frac{a}{b},b\) 的正负,\(-\frac{a}{b}<0,b>0\) 的情况是平凡的。若点 \(p\) 合法,那么被 \(p\) 支配的点也合法,只需要预处理每个点能支配多少点。
解决其他情况的关键在于发现合法与非法、支配与非支配是完全等价的,即求得非法的非支配对数(及非法的点数)后也能算出合法支配对数。不同情况算不同的东西即可

问题被转化为了半平面数点,随机数据下有非常简洁的做法。
把平面分成 \(\sqrt{n}\times\sqrt{n}\) 块,那么期望每块中有 \(O(1)\) 个点。一条直线只会穿过 \(O(\sqrt{n})\) 个块,对这些块内的点暴力,整块的点可以对每列做前缀和求出。时间复杂度 \(O(n\sqrt{n})\)

实现上可能需要处理直线与块顶点相交的情况,不过块大小是自己定的应该不会出现,所以直接不管(

我的写法比较粗暴,卡常时间几乎和写代码时间持平,体验极差

code
const int N = 2e5+5, X = 1e4, B = 128, BN = N/B+5;
int n,m,bn;
short *in,le[BN],ri[BN];
LL a,b,c;
double k1,k2;
Pii p[N];
Vi id[BN][BN];

#define x(i) p[i].fi
#define y(i) p[i].se
#define bx(i) in[x(i)]
#define by(i) in[y(i)]

struct {
	int t[int(2e4+2)];
	void clr() { memset(t,0,sizeof t); }
	void add(int i) { for(i+=X+1;i<=2e4+1;i+=i&-i)++t[i]; }
	int sum(int i) { int res=0; for(i+=X+1;i;i-=i&-i)res+=t[i]; return res; }
	int sum(int l,int r) { return sum(r) - sum(l-1); }
} bit;

namespace sub {
LL pre[N],suf[N];
void init() {
	bit.clr(); for(int l = 1, r; l <= n; l = r+1) {
		for(r = l; r < n && x(r+1) == x(l); ++r);
		For(i,l,r) pre[i] = pre[i-1] + bit.sum(-X,y(i)-1);
		For(i,l,r) bit.add(y(i));
	}
	bit.clr(); for(int r = n, l; r; r = l-1) {
		for(l = r; l > 1 && x(l-1) == x(r); --l);
		rFor(i,r,l) suf[i] = suf[i+1] + bit.sum(y(i)+1,X);
		rFor(i,r,l) bit.add(y(i));
	}
}
void slv() {
	if( a > 0 ) {
		int l = 1, r = n+1, mid;
		while( l < r ) mid = l+r>>1, a*x(mid)+c>0 ? r=mid : l=mid+1;
		io<<suf[l]<<endl;
	} else {
		int l = 0, r = n, mid;
		while( l < r ) mid = l+r+1>>1, a*x(mid)+c>0 ? l=mid : r=mid-1;
		io<<pre[l]<<endl;
	}
}
}

struct Block {
	int w[N],s[BN][BN];
	void bld() {
		For(i,1,n) s[bx(i)][by(i)] += w[i];
		For(i,1,bn) rFor(j,bn,1) s[i][j] += s[i][j+1];
	}
	int cal(LL x) {
		LL y = k1 * x + k2;
		return y<-X ? 0 : y<=X ? in[y] : bn+1;
	}
} cnt;

struct : Block {
	void init() {
		bit.clr(); for(int r = n, l; r; r = l-1) {
			for(l = r; l > 1 && x(l-1) == x(r); --l);
			rFor(i,r,l) w[i] = bit.sum(y(i)+1,X);
			rFor(i,r,l) bit.add(y(i));
		}
		bld();
	}
	void slv() {
		LL res = 0;
		For(i,1,bn) {
			int l = cal(le[i]), r = cal(ri[i]); if( l > r ) swap(l,r);
			res += s[i][r+1];
			For(j,l,r) for(int k : id[i][j])
				if( a*x(k)+b*y(k)+c > 0 ) res += w[k];
		}
		io<<res<<endl;
	}
} cs1;

struct : Block {
	LL tot;
	void init() {
		bit.clr(); for(int l = 1, r; l <= n; l = r+1) {
			for(r = l; r < n && x(r+1) == x(l); ++r);
			For(i,l,r) w[i] = bit.sum(-X,y(i)-1);
			For(i,l,r) bit.add(y(i));
		} tot = accumulate(w+1,w+n+1,0ll);
		bld();
	}
	void slv() {
		LL res = tot;
		For(i,1,bn) {
			int l = cal(le[i]), r = cal(ri[i]); if( l > r ) swap(l,r);
			res -= s[i][r+1];
			For(j,l,r) for(int k : id[i][j])
				if( a*x(k)+b*y(k)+c <= 0 ) res -= w[k];
		}
		io<<res<<endl;
	}
} cs2;

struct : Block {
	void init() {
		bit.clr(); for(int l = 1, r; l <= n; l = r+1) {
			for(r = l; r < n && x(r+1) == x(l); ++r);
			rFor(i,r,l) w[i] = bit.sum(y(i),X), bit.add(y(i));
		}
		bld();
	}
	void slv() {
		LL n = 0, res = 0;
		For(i,1,bn) {
			int l = cal(le[i]), r = cal(ri[i]); if( l > r ) swap(l,r);
			n += cnt.s[i][r+1], res += s[i][r+1];
			For(j,l,r) for(int k : id[i][j])
				if( a*x(k)+b*y(k)+c > 0 ) ++n, res += w[k];
		}
		io<<n*(n-1ll)/2-res<<endl;
	}
} cs3;

struct : Block {
	LL tot;
	void init() {
		bit.clr(); for(int r = n, l; r; r = l-1) {
			for(l = r; l > 1 && x(l-1) == x(r); --l);
			For(i,l,r) w[i] = bit.sum(-X,y(i)), bit.add(y(i));
		} tot = accumulate(w+1,w+n+1,0ll);
		bld();
	}
	void slv() {
		LL n = ::n, res = tot;
		For(i,1,bn) {
			int l = cal(le[i]), r = cal(ri[i]); if( l > r ) swap(l,r);
			n -= cnt.s[i][r+1], res -= s[i][r+1];
			For(j,l,r) for(int k : id[i][j])
				if( a*x(k)+b*y(k)+c <= 0 ) --n, res -= w[k];
		}
		io<<n*(n-1ll)/2-res<<endl;
	}
} cs4;

signed main() { freopen("c.in","r",stdin); freopen("c.out","w",stdout);
	in = new short[20002]() + 10001;
	for(int i = -X; i <= X; i += B) in[i] = ++bn, le[bn] = i;
	For(i,1,bn) ri[i] = le[i]+B-1; ri[bn] = X;
	For(i,-X,X) if( !in[i] ) in[i] = in[i-1];
	io>>n>>m; For(i,1,n) io>>x(i)>>y(i); sort(p+1,p+n+1);
	For(i,1,n) id[bx(i)][by(i)].pb(i), cnt.w[i] = 1;
	sub::init(), cnt.bld(), cs1.init(), cs2.init(), cs3.init(), cs4.init();
	while( m-- ) {
		io>>a>>b>>c, k1 = (double)-a/b, k2 = (double)-c/b;
		if( !b ) sub::slv();
		else if( k1 < 0 ) b>0 ? cs1.slv() : cs2.slv();
		else b>0 ? cs3.slv() : cs4.slv();
	}
	return 0;
}
posted @ 2022-05-05 16:00  401rk8  阅读(67)  评论(2编辑  收藏  举报