洛谷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;
}