1. 程式人生 > 實用技巧 >洛谷7月月賽題解(2020)

洛谷7月月賽題解(2020)

洛谷7月月賽題解

一.前言

​ 醜話說在前面,我只寫了前三個的題解(因為有人告訴我第四題沒有價值!!)

二.可持久化動態仙人掌的直徑問題

​ 標題黨,廣大OIer看了直呼內行!真就簽到題唄。反正就是把冪魔改成開根向下取個整。看程式碼吧。

int main(){
	cin>>n>>m;
	cout<<(int)pow(n,1.00/m);
	return 0;
}

三.混凝土數學

​ 混,混凝土??(擦汗),哎呀不就等腰三角形嗎,分類討論一手等腰和等邊,選取 1~2*len-1 的邊進行一下組合運算,就像我這樣的蒟蒻才會放到桶裡做,dalao們都是直接排一手序然後二分查詢……不說了上程式碼

const int mod=998244353;
int n,maxx,x;
long long sum[200005],a[200005];
long long ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>x;
		a[x]++;
		maxx=max(maxx,x);
	}
	for(int i=1;i<=maxx;++i)sum[i]=(sum[i-1]+a[i])%mod;
	for(int i=1;i<=maxx;++i){
		if(a[i]>=3)ans=(ans+(1LL*(a[i]*(a[i]-1)/2)*(a[i]-2))/3%mod)%mod;
		if(a[i]>=2){
			long long u=(sum[min(maxx,2*i-1)]-a[i]+mod)%mod;
			ans=(ans+((1LL*a[i]*(a[i]-1)/2%mod)*u)%mod)%mod;
		}
	}
	cout<<ans%mod;
	return 0;
}

四.論如何玩轉 Excel 表格

​ 首先,明確幾個基本點。

  • 旋轉180度之後,在同一列的兩個點還是在同一列。
  • 旋轉的本質是左上換右下與左下換右上
  • 對於任意一個數字,它在表格中的可移動軌跡呈'W'形

知道這些點後,那麼可以快速地判斷出無解的情況:1.該在同一列的不在同一列 2.不在'W'軌跡上,可以用奇偶判別法。

判斷完無解後,由於表格是由兩個'W'上下插在一起,同一列也是一一對應,所以只把其中的一條'W'拿出來給它拉直就好。於是我們得到兩個不包含重複元素的序列,求由這個序列轉換到另一個序列的最小運算元(操作為將相鄰的兩個數交換)。

​ 其實到這裡有一點氣泡排序的意思在裡面,如果變成轉換為升序直接逆序對就完事了。

​ 關於轉換成升序,很顯然數值並不是升序的,但是下標是。假設原序列為 a ,目標序列為 b,那麼對於一個 \(a_i\),b中有且只有一個(與上文的不包含重複元素相照應)與它值相同的 \(b_j\)\(b_j\) 的下標 j 放到 i 的位置去,構成一個新序列 c ,那麼c 轉化為升序就是答案,即 c 的逆序對數。(這裡有點繞,但是很重要)

​ 這裡我逆序對採用權值樹狀陣列,從後往前掃描,單點修改和求和(不會的我稍微講一下,由於從後往前,所以保證了在一個新點加入的時候樹狀陣列內的全是下標比他大的,於是求個和sum(a[i]-1)就得出了下標大但是數值小的個數,最後把 a[i] 對應的改為1)

然後程式碼裡面有個比較繞的指標……湊合著看,以及有兩個輔助的函式(魔改成define了,一個是知道列號給出W中的位置,一個是知道W中的位置給出列號)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<fstream>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define fz(x) (x>n?x-n:x)
#define fx(x) (x%2?x:x+n)
const int MAXN=2*1e6+5;
int n,a[MAXN],b[MAXN],to[MAXN],c[MAXN];
int read(){
	char ch=getchar();
	int res=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())res=res*10+(ch-'0');
	return res*f;
}
long long ans;
void add(int x){
	for(;x<=n;x+=lowbit(x))c[x]++;
}
int get(int x){
	int res=0;
	for(;x;x-=lowbit(x))res+=c[x];
	return res;
}
int main(){
	n=read();
	for(int i=1;i<=n*2;++i)to[(a[i]=read())]=i;
	for(int i=1;i<=n*2;++i)b[i]=read();
	for(int i=1;i<=n;++i){
		if(to[b[i]]<=n&&(i-fz(to[b[i]]))%2==1){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]>n&&(i-fz(to[b[i]]))%2==0){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]>n&&a[to[b[i]]-n]!=b[i+n]){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]<=n&&a[to[b[i]]+n]!=b[i+n]){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
	}
	for(int i=n+1;i<=2*n;++i){
		if(to[b[i]]<=n&&(i-n-fz(to[b[i]]))%2==0){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]>n&&(i-n-fz(to[b[i]]))%2==1){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]>n&&a[to[b[i]]-n]!=b[i-n]){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
		if(to[b[i]]<=n&&a[to[b[i]]+n]!=b[i-n]){
			cout<<"dldsgay!!1"<<endl;
			return 0;
		}
	}
	for(int i=n;i>=1;--i){
		int u=b[fx(i)];
		ans+=get(fz(to[u])-1);
		add(fz(to[u]));
	}
	cout<<ans;
	return 0;
}