诶,本来不打算写游记了
就香他一回吧...
话说大部分题目没有订正耶...
忽然发现 Day 和 Night 没什么区别于是...
Day 1
就讲模拟赛好了
T1
一道卡特兰数的拓展题,结果咱这只菜鸡连卡特兰数的通项公式都不会,于是暴力分拿稳
于是牢记卡特兰数通项公式: \(Cat[n]={C(2n,n)\over n+1}\)
疯狂容斥 ORZ
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iI;--i)
#define go(G,u) for(Rg int i=G.head[u],v=G.e[i].to;i;v=G.e[i=G.e[i].nxt].to)
#define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=5e6+3,M=5003;
typedef int arr[M];
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int dec(int x,int y){return (x-=y)<0?x+mod:x;}
inline int inc(int x,int y){return (x+=y)>=mod?x-mod:x;}
inline ll read(){ ll x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} int m,p,q,c,top,fac[N],inv[N]; arr x,y,tx,ty,f,id;
inline int C(int n,int m){return n=y[i]&&x[i]<=p&&y[i]<=q)
++top,tx[top]=x[i],ty[top]=y[i]; //加入有效点
++top,tx[top]=ty[top]=0;
++top,tx[top]=p,ty[top]=q;
fp(i,1,top) id[i]=i;
sort(id+1,id+1+top,cmp);
f[1]=mod-1;
fp(i,2,top){ //容斥
fp(j,1,i-1) if(tx[id[j]]<=tx[id[i]]&&ty[id[j]]<=ty[id[j]])
f[i]=inc(f[i],mul(f[j],calc(tx[id[j]],ty[id[j]],tx[id[i]],ty[id[i]])));
f[i]=dec(0,f[i]);
} return !printf("%d\n",f[top]);
}
T2
水题?从一号点出发一路异或跑大法师然后沿途的点丢进 trie 树维护并查询...
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iI;--i)
#define go(u) for(Rg int i=head[u],v=e[i].to;i;v=e[i=e[i].nxt].to)
#define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
#define ll long long
using namespace std;
const int M=1e6+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline void cmax(int& x,int y){if(x>=1;
}
inline void update(int x){
Divide(x); Rg int now=1;
fd(i,29,0){
if(!son[now][d[i]])
son[now][d[i]]=++cnt;
now=son[now][d[i]];
}
}
inline int query(int x){
Divide(x); Rg int now=1,tmp=0;
fd(i,29,0){
if(son[now][d[i]^1])
tmp|=1<
T3
没错咕掉了
30 暴力稳稳
正解好像是矩阵上 update 乱维护,反正咱不会
//by Judge
#pragma GCC optimize("Ofast")
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iI;--i)
#define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
#define ll long long
using namespace std;
const int M=2e5+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int Max(int x,int y){return x>y?x:y;}
inline int Min(int x,int y){return x1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,q,op,x; arr a,f;
int main(){
open("set"); n=read(),q=read();
if(n>100) return 0;
fp(i,1,n) a[i]=read();
sort(a+1,a+1+n),f[1]=1e9,f[2]=a[2]-a[1];
fp(i,3,n) f[i]=(a[i]-a[i-1])+Min(f[i-1],f[i-2]);
fp(stp,1,q){
op=read(),x=read();
if(op&1){
int k=lower_bound(a+1,a+1+n,x)-a;
++n; fd(i,n,k+1) a[i]=a[i-1];
a[k]=x,f[2]=a[2]-a[1];
fp(i,Max(k,3),n) f[i]=(a[i]-a[i-1])+Min(f[i-1],f[i-2]);
} else{
int k=lower_bound(a+1,a+1+n,x)-a;
--n; fp(i,k,n) a[i]=a[i+1];
f[2]=a[2]-a[1];
fp(i,Max(k,3),n) f[i]=(a[i]-a[i-1])+Min(f[i-1],f[i-2]);
}
print(f[n]);
// cerr<
Day 2
ORZ 原地爆炸, T1 狗屎卡内存.jpg
T1
没错此题卡内存,正解布隆过滤器?听都没听过
于是用了 xzy 巨佬的重开文件 + 双模的 hash_map
大体思路是我们先把所有树以 1e6 为模数搞一个 hash 值,然后分成十部分处理,这样的话每个部分均摊下来有小于 5e4 个字符串,然后每次弄 1e5 个 head 足以
那么保险起见我们还要用 1e9+7 双模一下存进上述的 hash_map
这样的正确率可以做到很高,但是还是会被叉的...原理就是我特意让这十个部分的某一块有极多的字符串(也就是说字符串数量不均摊了),这样的话是会数组越界的...
但被叉的条件是出题人看着你代码卡,或者 ccf 上使用 对拍 之类的人类智慧...
所以被叉的概率比较小...(就打比赛而言)
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i ans;
struct hash_map{ int pat,head[100003];
struct Edge{int to,nxt;}e[N];
inline void clear(){
pat=0,memset(head,0,sizeof head);
}
inline void insert(int u,int x){
e[++pat]=(Edge){x,head[u]},head[u]=pat;
}
inline bool find(int u,int x){
go(u) if(e[i].to==x) return 1; return 0;
}
}mp;
inline void ReOpen(){
fclose(stdin),freopen("XVII.in","r",stdin);
p1=p2=NULL,mp.clear();
}
inline int getHash(int bas,int mod){ int Hash=0;
fp(i,1,32) Hash=(Hash*bas+s[i])%mod; return Hash;
}
int main(){
open("XVII");
for(Rg ull L=0,R;L<1e6;L=R+1){
scanf("%d",&n),R=L+1e5-1;
fp(i,1,n){ sread(s),Hash=getHash(233,1e6);
if(L<=Hash&&Hash<=R){
int u=Hash-L; Hash=getHash(817,1e9+7);
if(mp.find(u,Hash)) ans[i]=1;
else mp.insert(u,Hash);
}
} ReOpen();
}
fp(i,1,n) puts(ans[i]?"Yes":"No");
return 0;
}
到时候补正解 ORZ
正解也挺短的ORZ
话说这个布隆过滤器正确率真的玄学...按照公式选了组最优参数结果 WA 上天
然后就是一系列面向数据编程最终艰难躺过...
还有一点就是 bits 会占内存!(我说为什么莫名其妙多了一兆,咱记得之前抢最优解的时候好像有被这玩意儿坑过...)
于是乎牢记以后做到卡内存的题目千万不要用 bitset, 不然你精心构造的顶内存上界的代码可能会光荣爆炸...
//by Judge
#include
#include
#include
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i mp; int val[21];
inline int getHash(int x){ ull Hash=0;
fp(i,1,32) Hash=(Hash*bas[x]+s[i])%mod[x];
return Hash;
}
int main(){ open("XVII");
scanf("%d",&n);
fp(stp,1,n){ sread(s),flg=1;
fp(i,1,K){
val[i]=getHash(i);
flg&=mp[val[i]];
}
if(flg) puts("Yes");
else{ puts("No");
fp(i,1,K) mp[val[i]]=1;
}
} return 0;
}
T2
ORZ 第二题永远友好一些(flag 就立这儿了STO)
如果只有一个点的话我们直接输出 1 就好了(ORZ)
考虑固定一个点,剩余的 n-1 个点只能在第一个点左边的 \(2π\over x\) 范围内,那么概率就是 \({1\over x^{n-1}}\)
然后我们考虑可以令 n 个点中的任意一个点在最右边,那么总概率就是 \(n\over x^{n-1}\)
代码极短.jpg
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iI;--i)
#define go(G,u) for(Rg int i=G.head[u],v=G.e[i].to;i;v=G.e[i=G.e[i].nxt].to)
#define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
#define ll long long
using namespace std;
const int mod=998244353;
inline int qpow(int x,int p=mod-2){ Rg int s=1;
for(;p;p>>=1,x=1ll*x*x%mod) if(p&1) s=1ll*s*x%mod; return s;
}
int main(){ int n,x;
open("ran"); cin>>n>>x;
if(n<2) return !puts("1");
return !printf("%lld\n",1ll*n*qpow(qpow(x),n-1)%mod);
}
T3
同理,咱打都没打,看着就是点双 X 圆方树,但是口胡谁都会,谁会来打啊woc...
ORZ 找不到源代码的 zjq 表示一脸迷茫...
Day 3
ORZ 原地爆炸祭
ZJQ 打完 T1 T3 以及 T2 的暴力之后就去浪 混乱*战了于是发现出题人数据水的一 P + 莫名 wa 掉 T2 最后原地爆炸
T1
ORZ 疯狂敲椰子,没打过 CC 的 JZ 出考场一脸懊悔然后用乱搞算法 0MS A 了此题
没什么好讲的, \(N^2k\) dp 用斜率优化就是正解 了
ORZ std半平面交...
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iy)x=y;}
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} int n,ans=2e9,k,head,tail; arr a,q,f,g;
#define X(i) (i)
#define Y(i) (f[i])
inline bool cmp(int x,int y){return x>y;}
inline int rate(int j,int k){ return (Y(k)-Y(j))/(X(k)-X(j)); }
int main(){
open("chest");
n=read(),k=read();
fp(i,1,n) a[i]=read();
sort(a+1,a+1+n,cmp);
memset(g,0x3f, (n+2)<<2),g[0]=0;
fp(i,1,k){
memcpy(f,g,(n+2)<<2),q[head=tail=1]=i-1;
fp(j,i,n){
while(head=a[j]) --tail;
g[j]=f[q[tail]]+(j-q[tail])*a[j];
while(head=rate(q[tail],j)) --tail;
q[++tail]=j; if(i==k) cmin(ans,g[j]);
}
}
// cerr<
T2
ORZ 开 40 棵线段树的 JZ...
咱用两个单调栈的方法,复杂度两只 log
简而言之就是两只单调栈 + 线段树按位维护
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i>1;
sum[ls]+=(mid-l+1)*tag[k],sum[rs]+=(r-mid)*tag[k];
tag[ls]+=tag[k],tag[rs]+=tag[k],tag[k]=0;
}
void update(int k,int l,int r,int L,int R,int v){
if(L<=l&&r<=R) return tag[k]+=v,sum[k]+=v*(r-l+1),void();
if(L>r||l>R) return ; int mid=(l+r)>>1; pushdown(k,l,r);
update(lson,L,R,v),update(rson,L,R,v),sum[k]=sum[ls]+sum[rs];
}
int query(int k,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[k]; if(L>r||l>R) return 0; int mid=(l+r)>>1;
pushdown(k,l,r); return query(lson,L,R)+query(rson,L,R);
}
}t[2][19];
inline void add(int h,int x,int l,int r,int v){
fp(i,0,18) if((x>>i)&1){
now+=1ll*t[h^1][i].query(1,1,n,l,r)*v*(1<a[q1[top1]])
add(0,a[q1[top1]],q1[top1-1]+1,q1[top1],-1),--top1;
q1[++top1]=i,add(0,a[i],q1[top1-1]+1,i,1);
while(top2&&a[i]
T3
据说此题最简单然鹅 T1 的数据告诉我们可能并不是这样的
考虑右端点排序去掉非优课程后得到的序列左端点和右端点必然都是递增的
如果询问只有一个,那么我们肯定是贪心地从头选到尾,能加的就加
那么咱发现每个点的后继点是唯一的确定的,这样会构成一棵内向树,但树可能有很多棵,那么就会构成内向树森林
我们在每棵树上倍增祖先,然后每次倍增找右端点不超过 R 的祖先就好了
代码用了 STL 跑的飞快,不开 O2 是蓝指导的 4 倍开完就变 9 倍 ORZ
//by Judge
#include
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;iI;--i)
#define go(u) for(Rg int i=head[u],v=e[i].to;i;v=e[i=e[i].nxt].to)
#define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
#define ll long long
using namespace std;
const int M=1e5+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){ ll x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(ll x,char chr='\n'){
if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,m,Q,pat,f[M][17]; arr vis,head,dep;
struct Edge{ int to,nxt; }e[M];
inline void add(int u,int v){
e[++pat]=(Edge){v,head[u]},head[u]=pat;
}
struct node{ int l,r; node(){} node(int _l,int _r=-1){l=_l,r=_r;}
bool operator <(const node& b)const{ return ly.l;
}
inline void Unique(){
fp(i,1,m) if(a[i].l>b[n].l) b[++n]=a[i];
}
void dfs(int u){
fp(j,1,16) f[u][j]=f[f[u][j-1]][j-1];
go(u) f[v][0]=u,dep[v]=dep[u]+1,dfs(v);
}
inline void build(){
fp(i,1,n){
Rg int fa=upper_bound(b+1,b+1+n,node(b[i].r))-b;
if(fa<=n) add(fa,i),vis[i]=1;
}
fp(i,1,n) if(!vis[i]) dfs(i);
}
inline int find(int u,int R){
fd(j,16,0) if(b[f[u][j]].r<=R) u=f[u][j]; return u;
}
int main(){
open("course");
m=read(),Q=read(),b[0].r=2e9;
fp(i,1,m) a[i].l=read(),a[i].r=read();
sort(a+1,a+1+m,cmp),Unique(),build();
while(Q--){
Rg int L=read(),R=read(),x;
x=lower_bound(b+1,b+1+n,node(L))-b;
if(x>n||b[x].r>R) print(0);
else print(dep[x]-dep[find(x,R)]+1);
// cerr<<(x<=n&&b[x].r<=R?(dep[x]-dep[find(x,R)]+1):0)<
坐等 tomorrow boring