[JSC2021 A~D + F]

半小时打完了\(A~D\),想要一发\(F\)冲进前\(100\),结果平衡树常数大\(T\)了。据说\(G\)是矩阵树定。

\(A\)

放代码吧。

A
// code by Dix_
#include<bits/stdc++.h>
#define ll long long

inline ll read(){
   char C=getchar();
   ll N=0 , F=1;
   while(('0' > C || C > '9') && (C != '-')) C=getchar();
   if(C == '-') F=-1 , C=getchar();
   while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
   return F*N;
}

ll x,y,z;

int main(){
   x = read(),y = read(),z = read();
   if(y * z % x != 0)
   std::cout<<(ll)y * z / x;
   else
   std::cout<<(ll)y * z / x - 1<<std::endl;
}

\(B\)
按题意模拟

B
// code by Dix_
#include<bits/stdc++.h>
#define ll long long
#define M 1000000

inline ll read(){
   char C=getchar();
   ll N=0 , F=1;
   while(('0' > C || C > '9') && (C != '-')) C=getchar();
   if(C == '-') F=-1 , C=getchar();
   while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
   return F*N;
}

ll num[M];
ll n,m;

int main(){
   n = read(),m = read();
   for(int i = 1;i <= n;++i){
   ll x = read();
   if(num[x] == 0)
   num[x] ++ ;
   }
   for(int i = 1;i <= m;++i){
   ll x = read();
   num[x] ++ ;
   }
   for(int i = 1;i <= M;++i)
   if(num[i] == 1)
   std::cout<<i<<" ";
}

\(C\)

考虑枚举这个最大的公约数,把这个公约数的倍数在小于\(m\)情况下求出第二大的,看是否大于\(n\)

C
// code by Dix_
#include<bits/stdc++.h>
#define ll long long
#define M 1000000
 
inline ll read(){
    char C=getchar();
    ll N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N;
}
 
ll num[M];
ll n,m;
 
bool s(int a){
	for(int i = 2;i < sqrt(a);++i)
	if(a % i == 0)
	return false;
	return true;
}
 
int main(){
	n = read(),m = read();
	for(int i = m;i >= 1;--i){
		ll x = m / i * i - i;
		ll y = m / i * i;
		if(x >= n){
			std::cout<<i;
			return 0;
		}
	}
}

\(D\)

考虑第一位有\(p - 1\)种选择,以后每个位根据前面的和的膜,只有\(p-2\)

D
// code by Dix_
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
 
inline ll read(){
    char C=getchar();
    ll N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N;
}
 
ll n,p;
 
ll power(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b & 1)ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}
 
int main(){
	n = read();
	p = read();
	p -= 1;
	std::cout<<(p * power(p - 1,n - 1)) % mod<<std::endl;
}
 

\(F\)

考虑改变一个数时,在另外一个序列里找到原数的贡献,和现在这个数的贡献。
并在这个序列中删掉原数,加入新数。
用平衡树操作,只要查询前缀,前缀和,还有删除插入操作

放一下考场代码,被卡常了,找时间再改吧。

F
// code by Dix_
#include<bits/stdc++.h>
#define ll long long
#define M 200005
 
inline ll read(){
    char C=getchar();
    ll N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N;
}
 
ll n,m,q;
 
ll a[M],b[M],suma,sumb;
 
ll ans = 0;
 
struct P{
#define A 2000010
 
ll ch[A][2],val[A],cv[A],siz[A],cnt,sum[A];
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define v(x) val[x]
#define c(x) cv[x]
#define s(x) siz[x]
#define sa(x) sum[x]
 
void up(ll x){s(x) = 1 + s(l(x)) + s(r(x)),sa(x) = v(x) + sa(l(x)) + sa(r(x));}
 
ll randoom(){return rand() << 15 | rand();}
 
ll newcode(ll x){s(++cnt) = 1,sa(cnt) = v(cnt) = x,c(cnt) = randoom();return cnt;}
 
void split(ll now,ll k,ll &x,ll &y){
	if(!now){x = y = 0;return;}
	if(v(now) <= k) x = now,split(r(now),k,r(now),y);
	else
	y = now,split(l(now),k,x,l(now));
	up(now);
}
 
ll merge(ll x,ll y){
	if(!x || !y)return x + y;
	if(c(x) < c(y)){
		r(x) = merge(r(x),y);
		up(x);return x;
	}
	else{
		l(y) = merge(x,l(y));
		up(y);return y;
	}
}
 
ll root,x,y,z,cn;
 
void insert(ll a){
	cn ++ ;
	split(root,a,x,y);
	root = merge(merge(x,newcode(a)),y);
}
 
void del(ll a){
	cn -- ;
	split(root,a,x,z);
	split(x,a - 1,x,y);
	y = merge(l(y),r(y));
	root = merge(x,merge(y,z));
}
 
ll find(ll a){
	split(root,a - 1,x,y);
	ll ans = s(x) + 1;
	root = merge(x,y);
	return ans;
}
 
ll kth(ll now,ll k){
	if(k <= s(l(now)))return kth(l(now),k);
	else
	if(k == s(l(now)) + 1)return now;
	else
	return kth(r(now),k - s(l(now)) - 1);
}
 
ll pre(ll a){
	split(root,a,x,y);
	ll ans = s(x);
	merge(x,y);
	return ans;
}
 
ll nex(ll a){
	split(root,a,x,y);
	ll ans = v(kth(y,1));
	merge(x,y);
	return ans;
}
 
ll prev(ll a){
	split(root,a,x,y);
	ll ans = sa(kth(x,s(x)));
	merge(x,y);
	return ans;
}
 
}Q,P;//A B
 
ll tob(int x){
	ll l = sumb - P.prev(x);
//	std::cout<<l<<std::endl;
	ll k = P.pre(x) * x;
//	std::cout<<k<<std::endl;
	return l + k;
}//在b里找贡献。
 
ll toa(int x){
	ll l = suma - Q.prev(x);
	ll k = Q.pre(x) * x;
	return l + k;
}//在b里找贡献。
 
int main(){
	n = read(),m = read(),q = read();
	for(int i = 1;i <= n;++i)
	Q.insert(0);
	for(int i = 1;i <= m;++i)
	P.insert(0);
	while(q -- ){
		ll t = read(),x = read(),y = read();
		if(t == 1){
			ans += tob(y) - tob(a[x]);
			suma += y - a[x];
			Q.del(a[x]),Q.insert(y);
			a[x] = y;
		}
		if(t == 2){
			ans += toa(y) - toa(b[x]);
			sumb += y - b[x];
			P.del(b[x]),P.insert(y);
			b[x] = y;
		}
		std::cout<<ans<<std::endl;
	}
}

\(rank 800\)果真还是逊啊。

posted @ 2021-04-18 13:07  fhq_treap  阅读(95)  评论(0编辑  收藏  举报