WHU校赛2019(网络赛) 解题报告(CCNU_你们好强啊我们都是面包手) Apare_xzc
WHU校赛2019(网络赛) 解题报告
CCNU_你们好强啊我们都是面包手(xzc zx lj)
战况: 比赛时3题,排名57,现在5题了
题目链接: WHU校赛2019 <-戳这里
以下题目按难度顺序递增叙述
B.DrunkHamster
求两点之间距离的平方,签到题
/* Apr/07/2019 13:49UTC+8 CCNU_你们好强啊我们都是面包手 B - DrunkHamster GNU C++17 Accepted 30 ms 0 KB */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 1e5+100;
void solve(int x,int y)
{
LL ans = (1ll*x*x+1ll*y*y);
cout<<ans<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
LL x,y,z;
int T,n;
cin>>T;
int ca = 0;
while(T--)
{
x = y = 0;
scanf("%d",&n);
For(i,0,n-1)
{
scanf("%I64d",&z);
if(i%4==0) y += z;
else if(i%4==1) x+=z;
else if(i%4==2) y-=z;
else x-=z;
}
printf("Case #%d:",++ca);
solve(x,y);
}
return 0;
}
E.Egnima
简单模拟,搞个map或者数组对应,比较字符串即可
/* Apr/07/2019 14:03UTC+8 CCNU_你们好强啊我们都是面包手 E - Egnima GNU C++17 Accepted 31 ms 2100 KB */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 1e6+100;
char a[] = "abcdefghijklmnopqrstuvwxyz";
char b[] = "22233344455566677778889999";
map<char,char> mp;
char num[maxn],str[maxn];
int LenNum;
bool ok()
{
int len = strlen(str)-1;
if(len!=LenNum) return false;
For(i,0,len)
{
if(mp[str[i]]!=num[i]) return false;
}
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int len = strlen(a)-1;
For(i,0,len)
{
mp[a[i]] = b[i];
}
int T,n;
cin>>T;
int ca = 0;
while(T--)
{
printf("Case #%d:\n",++ca);
scanf("%s",num);
LenNum = strlen(num)-1;
scanf("%d",&n);
For(ca,1,n)
{
scanf("%s",str);
if(ok())
{
printf("Maybe..\n");
}
else
{
printf("How could that be possible?\n");
}
}
}
return 0;
}
D.Dandelion
卡特兰数 C(m+n-1,n-1)-C(m+n-1,m-1))
预处理阶乘以及阶乘的逆元即可
打比赛的前一天我在牛客上写了道类似的题
感谢lj正确的公式,是我写呲了,忘记%mod+mod%mod,wa了一发,我的锅
/* Apr/07/2019 14:44 UTC+8 CCNU_你们好强啊我们都是面包手 D - Dandelion GNU C++17 Accepted 62ms 31300 KB */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 2e6+100;
const int mod = 1e9+7;
LL r[maxn];
LL fac[maxn];
LL fast_pow(LL a,LL b);
void init();
LL C(int n,int m);
int main()
{
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T,m,n;
init();
cin>>T;
while(T--)
{
scanf("%d%d",&m,&n);
LL ans = ((C(m+n-1,max(m,n)-1)-C(m+n-1,min(m,n)-1))%mod+mod)%mod;
printf("%I64d\n",abs(ans));
}
return 0;
}
LL fast_pow(LL a,LL b)
{
LL ans = 1;
while(b)
{
if(b&1) ans = ans*a%mod;
a = a*a%mod;
b>>=1;
}
return ans;
}
void init()
{
fac[0] = 1;
r[0] = 1;
For(i,1,2000000) fac[i] = fac[i-1]*i%mod;
r[2000000] = fast_pow(fac[2000000],mod-2);
Rep(i,1999999,1)
r[i] = r[i+1]*(i+1)%mod;
}
LL C(int n,int m)
{
if(n<m||m<0) return 0;
return fac[n]*r[m]%mod*r[n-m]%mod;
}
C.Store
题意:
n种货物
M x y:在第x天买了第y种货物
D x y: 查询在之前比x小的天数中卖过的货物>=y的最小值
1<=y<=n<=1e5 x<=1e9
思路:
- 线段树,把x离散化,按x建立线段树,线段树每个节点开一个set,存这个区间里已经卖出去的y(货物种类)
- 单点更新,区间查询
- 这题还不难,但比赛的时候作为数据结构手的我去搞没做过的主席树了… 还是我的锅,不过今天上算法课写了一发,补出来了
/* Apr/08/2019 15:43UTC+8 CCNU_你们好强啊我们都是面包手 C - Store GNU C++17 Accepted 794 ms 61900 KB */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 2e5+3;
int a[maxn],p[maxn];
set<int>::iterator it;
struct SegmentTree{
set<int> s;
}tree[maxn<<2];
struct Question{
char tp[2];
int x,y;
}qu[maxn];
void update(int left,int right,int tx,int ty,int pos=1)
{
tree[pos].s.insert(ty);
if(left==right) return;
int mid = (left+right)>>1;
if(tx<=mid) update(left,mid,tx,ty,pos<<1);
else update(mid+1,right,tx,ty,pos<<1|1);
}
int query(int left,int right,int qx,int qy,int ty,int pos=1)
{
if(left>qy || right<qx)
{
return -1;
}
if(qx<=left && right<= qy)
{
it = tree[pos].s.lower_bound(ty);
if(it==tree[pos].s.end()) return -1;
return *it;
}
int mid = (left+right)>>1;
int ansL = query(left, mid,qx,qy,ty,pos<<1);
int ansR = query(mid+1,right,qx,qy,ty,pos<<1|1);
if(ansL==-1&&ansR==-1) return -1;
else if(ansL==-1) return ansR;
else if(ansR==-1) return ansL;
return min(ansL,ansR);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,Q;
scanf("%d%d",&n,&Q);
For(i,1,Q)
{
scanf("%s%d%d",qu[i].tp,&qu[i].x,&qu[i].y);
p[i] = qu[i].x;
}
sort(p+1,p+1+Q);
int Maxx = 0;
For(i,1,Q)
{
qu[i].x = lower_bound(p+1,p+1+Q,qu[i].x)-p;
Maxx = max(Maxx,qu[i].x);
}
For(i,1,Q)
{
if(qu[i].tp[0]=='M') update(1,Maxx,qu[i].x,qu[i].y);
else printf("%d\n",query(1,Maxx,1,qu[i].x,qu[i].y));
}
return 0;
}
F. Climb
- 树上第K小板子题(不过这是第K大)
- 今天学了一下,过了poj-2104,spoj-10628,学会了
- LCA是我上上周学的,dfs+RMQ
- 今天看卿爷和Y_Cl区间第K大的板子,感觉很好用
- 于是根据主席树的原理,写出了树上第K大~
- 这是我最近写的最长,开的数组最多的代码了
/* Apr/08/2019 22:10UTC+8 CCNU_你们好强啊我们都是面包手 F - Climb GNU C++17 Accepted 1294 ms 59200 KB */
Apr/09/2019 06:22UTC+8 CCNU_你们好强啊我们都是面包手 F - Climb GNU C++17 Accepted 1294 ms 59200 KB
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Mst(a,b) memset(a,(b),sizeof(a))
using namespace std;
const int maxn = 1e5+20;
int a[maxn],p[maxn],n,cnt;//p离散化
struct Edge{
int to,Next;
}edge[maxn<<1];
int head[maxn],totEdge;//邻接表
int First[maxn],sequence[maxn<<1],deep[maxn<<1];
int father[maxn];
bool vis[maxn]; //dfs
int Min[maxn<<1][20];
int Log2[maxn<<1]={-1};
struct Node{
Node * Lchild, * Rchild;
int sum;
}node[maxn*20],*root[maxn*20];
Node * update(int,int,int,Node*);
void build(); //建第一课空树(爷爷节点)
void initG(); //初始化邻接表
void addedge(int u,int v);
void dfs(int x,int fa,int deep,int&);
void getST(int n);
int LCA(int x,int y);
int query(int,int,int,Node*,Node*,Node*,Node*);
int main()
{
//freopen("in.txt","r",stdin);
For(i,1,maxn*2-15) Log2[i] = Log2[i>>1]+1;
int T,m;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
For(i,1,n) scanf("%d",a+i), p[i] = a[i];
sort(p+1,p+1+n);
For(i,1,n) a[i] = lower_bound(p+1,p+1+n,a[i])-p;
int u,v;
initG();
For(i,2,n)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
build(); //先建一棵空树
Mst(vis,0);
int cntOfSequence = 0;
dfs(1,0,1,cntOfSequence); //dfs生成树的同时,在父节点基础上建立新的线段树
int k,lca;
getST(2*n-1); //线性预处理(nlogn)
while(m--)
{
scanf("%d%d%d",&u,&v,&k);
lca = LCA(u,v);
int totNum = deep[First[u]]+deep[First[v]]-deep[First[lca]]-deep[First[father[lca]]];
if(k>totNum) //询问的K大于这条路径上所有顶点的个数
{
printf("-1\n");
continue;
}
k = totNum - k+1;
printf("%d\n",p[query(1,n,k,root[u],root[v],root[lca],root[father[lca]])]);
}
}
return 0;
}
void initG()
{
Mst(head,-1);
totEdge = 0;
}
void addedge(int u,int v)
{
edge[totEdge].to = v;
edge[totEdge].Next = head[u];
head[u] = totEdge++;
}
void dfs(int x,int fa,int dep,int &cntOfSeq)
{
father[x] = fa;
vis[x] = true;
root[x] = update(1,n,a[x],root[fa]);
sequence[++cntOfSeq] = x;
deep[cntOfSeq] = dep;
First[x] = cntOfSeq;
for(int i=head[x];i!=-1;i=edge[i].Next)
{
int to = edge[i].to;
if(vis[to]) continue;
vis[to] = true;
dfs(to,x,dep+1,cntOfSeq);
sequence[++cntOfSeq] = x;
deep[cntOfSeq] = dep;
}
}
void getST(int n)
{
For(i,1,n) Min[i][0] = i;
for(int j=1;(1<<j)<=n;++j)
{
for(int i=1;i+(1<<j)-1<=n;++i)
{
int a = Min[i][j-1];
int b = Min[i+(1<<(j-1))][j-1];
Min[i][j] = deep[a]>deep[b]?b:a;
}
}
}
int LCA(int x,int y)
{
x = First[x];
y = First[y];
if(x>y) swap(x,y);
int j = Log2[y-x+1];
int a = Min[x][j];
int b = Min[y-(1<<j)+1][j];
return deep[a]>deep[b]?sequence[b]:sequence[a];
}
Node * update(int left,int right,int v,Node * p)
{
if(v<left||v>right) return p;
Node * t = &node[cnt++];
t->Lchild = p->Lchild;
t->Rchild = p->Rchild;
t->sum = p->sum + 1;
if(left==right) return t;
int mid = (left+right)>>1;
t -> Lchild = update(left,mid,v,p->Lchild);
t -> Rchild = update(mid+1,right,v,p->Rchild);
return t;
}
void build()
{
cnt = 0;
root[0] = &node[cnt++];
root[0]->Lchild = root[0]->Rchild = root[0];
root[0]->sum = 0;
}
int query(int left,int right,int k,Node*ru,Node*rv,Node *rlca,Node*rfalca)
{
if(left==right) return left;
int tot = ru->Lchild->sum + rv->Lchild->sum
- rlca->Lchild->sum - rfalca->Lchild->sum;
int mid = (left+right)>>1;
if(k<=tot)
return query(left,mid,k,ru->Lchild,rv->Lchild,rlca->Lchild,rfalca->Lchild);
else
return query(mid+1,right,k-tot,ru->Rchild,rv->Rchild,rlca->Rchild,rfalca->Rchild);
}
队友们,我们一起加油叭!
好好训练,备战湘潭赛!
fighting!