1. 程式人生 > 其它 >20210811 Dove 打撲克,Cicada 與排序,Cicada 拿衣服

20210811 Dove 打撲克,Cicada 與排序,Cicada 拿衣服

考場

開考感覺 T3 比較可做。T1 看上去不難但毫無思路。
先想了 25min T3,想到一個確定左端點,二分最長的右端點,甚至想到了用貓樹維護區間 or and。。。上廁所回來發現假了,沒有單調性
T1 還是不會做,T2 甚至不會寫暴力。直到 8.10 才結束思考。

T1 暴力有 80pts,先寫了
繼續看 T3,根據區間變大後四個變數的變化情況想到了分治,又是想了很久發現複雜度假了,心態就炸了。這時候已經 9.20 了,洗了把臉強行冷靜,寫了 T3 暴力,但狀態很差,寫錯很多細節。
最後 30min 看 T2,感覺可以列舉 rnd() 的值來算出每種情況下的位置,覺得不太好寫在歸併排序,預處理了的個數組假裝它是隨機數。但預處理多長卻不好確定。一開始是 \(n\)

,但樣例都過不去,瞎胡分析一波感覺是每個數值的元素個數減一的和,也不太對。最終預處理的 \(21\) 位。

res

rk10 80+15+28
T2 後面的點都 T 了,開到 \(20\) 能多拿 20pts

rk1 熊子豪 100+0+92
rk2 yzf 80+0+100
rk3 肖鳴孜 80+100+0

總結

沒啥好說的,就是菜

T1 畢竟沒想多久,算是有個藉口

T2 又是大 DP,練了這麼久還是沒啥長進,甚至一點思路都沒有。不僅有人場切,而且很多人(比如 ycx)都有思路,只是細節問題/沒寫完。不擅長不是藉口,萬一正式比賽考出來怎麼辦,還是得練。練習的時候多自己想,能抵抗多久題解的誘惑提高就有多少

T3 想了很久都沒想到點上,還是性質推的不夠,確實也沒見過這種做法,但還是很多人想出來了。不僅如此,有人常數小拿了 64pts,有人的亂搞 A 了,也有 72pts 的,但我只拿了最基礎的暴力分,對於這種資料有梯度的題就要多卡常、多剪枝,剪枝可以大膽一點。

感覺洗臉挺有用的,起碼暴力沒掛分。

sol

雙沒時間寫了

T1
const int N = 1e5+5;
int n,m;

int mx,fa[N],val[N],cnt[N];
vector<int> vec;

int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]); }

void add(int i)
	{ if( !cnt[i]++ ) vec.insert(lower_bound(vec.begin(),vec.end(),i),i); }
void del(int i)
	{ if( !--cnt[i] ) vec.erase(remove(vec.begin(),vec.end(),i)); }

signed main() {
	read(n,m);
	For(i,1,n) fa[i] = i, val[i] = 1, add(1);
	while( m-- ) {
		int op,x,y; read(op);
		if( op == 1 ) {
			read(x,y); x = find(x), y = find(y);
			if( x == y ) continue;
			del(val[x]), del(val[y]);
			fa[y] = x, val[x] += val[y];
			add(val[x]);
		} else {
			read(x);
			LL ans = 0, suf = 0;
			if( !x ) {
				for(int i : vec) ans += cnt[i] * (cnt[i]-1ll) / 2;
				++x;
			}
			for(auto it = vec.begin(); it != vec.end(); ++it) suf += cnt[*it];
			for(auto itl = vec.begin(), itr = itl; itr != vec.end(); ++itl) {
				while( itr != vec.end() && *itr-*itl < x ) suf -= cnt[*itr++];
				if( itr == vec.end() ) break;
				ans += cnt[*itl] * suf;
			}
			write(ans);
		}
	}
	return iocl();
}
T2

我寫了另一種 DP,時間複雜度也是 \(O(n^3)\),但不知道為什麼比 sol做法 跑得慢多了

const int N = 505, mod = 998244353, inv2 = 499122177;
int n,a[N];

LL f[N][N][N],g[N][N];

void merge(int u,int l,int r) {
	if( l == r ) return f[u][l][l] = 1, void();
	int mid = l+r>>1;
	merge(u+1,l,mid), merge(u+1,mid+1,r);
	memset(g,0,sizeof g);
	g[l][mid+1] = 1;
	For(i,l,mid+1) For(j,mid+1,r+1) if( i <= mid || j <= r ) {
		g[i][j] %= mod;
		if( j == r+1 ) g[i+1][j] += g[i][j];
		else if( i == mid+1 ) g[i][j+1] += g[i][j];
		else if( a[i] < a[j] ) g[i+1][j] += g[i][j];
		else if( a[i] > a[j] ) g[i][j+1] += g[i][j];
		else g[i+1][j] += g[i][j] * inv2 %mod, g[i][j+1] += g[i][j] * inv2 %mod;
	}
	For(i,l,r) For(j,l,mid+1) For(k,mid+1,r+1) if( j <= mid || k <= r ) {
		if( k == r+1 ) f[u][i][j+k-mid-1] += f[u+1][i][j] * g[j][k] %mod;
		else if( j == mid+1 ) f[u][i][j+k-mid-1] += f[u+1][i][k] * g[j][k] %mod;
		else if( a[j] < a[k] ) f[u][i][j+k-mid-1] += f[u+1][i][j] * g[j][k] %mod;
		else if( a[j] > a[k] ) f[u][i][j+k-mid-1] += f[u+1][i][k] * g[j][k] %mod;
		else f[u][i][j+k-mid-1] += (f[u+1][i][j]+f[u+1][i][k]) * g[j][k] %mod * inv2 %mod;
	}
	For(i,l,r) For(j,l,r) f[u][i][j] %= mod;
	sort(a+l,a+r+1);
}

signed main() {
	read(n);
	For(i,1,n) read(a[i]);
	merge(1,1,n);
	For(i,1,n) {
		LL ans = 0;
		For(j,1,n) ans += f[1][i][j] * j %mod;
		write(ans%mod,' ');
	}
	return iocl();
}

T3
const int N = 1e6+5;
int n,m,a[N];

struct Node { int r,o,an; int val() { return o-an; } };
list<Node> lis;

namespace st {
int lg[N],f[20][N],g[20][N];
void init() {
	For(i,2,n) lg[i] = lg[i>>1] + 1;
	For(i,1,n) f[0][i] = g[0][i] = a[i];
	For(j,1,19) for(int i = 1; i+(1<<j)-1 <= n; ++i)
		f[j][i] = max(f[j-1][i],f[j-1][i+(1<<j-1)]),
		g[j][i] = min(g[j-1][i],g[j-1][i+(1<<j-1)]);
}
int mx(int l,int r) { int k = lg[r-l+1]; return max(f[k][l],f[k][r-(1<<k)+1]); }
int mn(int l,int r) { int k = lg[r-l+1]; return min(g[k][l],g[k][r-(1<<k)+1]); }
}
namespace seg {
#define ls (u<<1)
#define rs (u<<1|1)
struct Node { int l,r,mx; } t[N*4];
void build(int u,int l,int r) {
	t[u].l = l, t[u].r = r, t[u].mx = -1;
	if( l == r ) return;
	int mid = l+r>>1;
	build(ls,l,mid), build(rs,mid+1,r);
}
void modify(int u,int l,int r) {
	if( l <= t[u].l && t[u].r <= r ) { ckmax(t[u].mx,r-l+1); return; }
	if( l <= t[ls].r ) modify(ls,l,r);
	if( t[rs].l <= r ) modify(rs,l,r);
}
void print(int u) {
	if( t[u].l == t[u].r ) { write(t[u].mx,' '); return; }
	ckmax(t[ls].mx,t[u].mx), ckmax(t[rs].mx,t[u].mx);
	print(ls), print(rs);
}
#undef ls
#undef rs
}

bool check(list<Node>::iterator it,int l,int r)
	{ return it->val()+st::mn(l,r)-st::mx(l,r) >= m; }

signed main() {
	read(n,m);
	For(i,1,n) read(a[i]);
	st::init(), seg::build(1,1,n);
	For(i,1,n) {
		for(auto it = lis.begin(); it != lis.end(); ++it)
			it->o |= a[i], it->an &= a[i];
		lis.pb(Node{i,a[i],a[i]});
		for(auto itl = lis.begin(), itr = itl; ++itr != lis.end(); )
			if( itl->val() == itr->val() ) lis.erase(itl), itl = itr;
			else ++itl;
		for(auto it = lis.begin(); it != lis.end(); ++it) if( check(it,it->r,i) ) {
			int l = 1, r = it->r;
			if( it != lis.begin() ) l = (--it)->r+1, ++it;
			while( l < r ) {
				int mid = l+r>>1;
				if( check(it,mid,i) ) r = mid;
				else l = mid+1;
			}
			seg::modify(1,l,i);
			break;
		}
	}
	seg::print(1);
	return iocl();
}