前言
考古了,现在才写。
已经忘了赛时历程了,就记得 T1 打了个错误率高达 \(\dfrac{1}{100000}\) 的乱搞做法(前后各连 \(\log\) 个 \(k\) 大值)然后被卡常了,后三道都没交不记得为啥了。
T1 星际联邦
std 是 \(O(m\log m)\) 的菠萝算法,但是被众人疯狂爆标。
正解是 \(O(n)\) 的,不考虑连通性的话每个点连前缀最大值或后缀最小值是最优的,考虑连通性,他只能去连接第一个大于他的位置以后的后缀最小值,其实就是先分组,再组间连边,正确性是保证的。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=3e5+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,a[N],f[N],e[N],mn[N]; ll ans;
inline int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
signed main()
{
freopen("star.in","r",stdin),freopen("star.out","w",stdout);
read(n),a[0]=-1e9; for(int i=1,x=0;i<=n;i++)
read(a[i]),f[i]=i,a[x]<a[i]?e[++m]=x=i:f[find(i)]=x;
mn[n+1]=1e9; for(int i=n;i;i--) mn[i]=min(mn[i+1],a[i]);
for(int i=1,x;i<=n;i++) if(i!=(x=find(i))) ans+=min(a[i]-a[x],mn[i+1]-a[i]);
for(int i=1;i<m;i++) ans+=mn[e[i+1]]-a[e[i]]; write(ans);
}
T2 和平精英
首先需要知道一些性质:
- \(x\&y\le \min(x,y),x|y\ge \max(x,y)\)。
- \(popcount(x\&y)\le \min(popcount(x),popcount(y)),popcount(x|y)\ge \max(popcount(x),popcount(y))\)。
针对第一个性质我们有了 \(O(q(n+v))\) 的枚举答案的做法,这是扯淡的,半分都没有。
针对第二个性质我们有了 \(O(q(n+\log v))\) 的做法,这已经是一个优秀的暴力了。
即对于每个枚举的 \(p\),若 \(popcount(a_i)<p\) 则扔到 \(\{或\}\) 里,若 \(popcount(a_i)>p\) 则扔到 \(\{与\}\) 里,否则对于 \(\{a_i\mid popcount(a_i)=p\}\) 的,发现他们应该全部相等,然后再丢到哪个里面就无所谓了,两边可以抵消掉。
然后发现只要加个线段树就可以通过此题,每个 \(ppcount\) 开一颗线段树,维护区间或、与以及数的个数即可,复杂度 \(O(n\log n\log v)\)。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
#define mid (l+r>>1)
#define ls (mid<<1)
#define rs (mid<<1|1)
using namespace std;
const int N=1e5+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,a[N];
struct aa
{
int oor,aand=(1<<30)-1,cnt;
inline aa operator + (const aa a) const
{return (aa){oor|a.oor,aand&a.aand,cnt+a.cnt};}
};
class segment_tree
{
private:
aa t[N<<1];
inline int count(int x,int res=0)
{for(int i=0;i<=30;i++) res+=(x>>i)&1; return res;}
public:
inline void build(int p,int l,int r,int d)
{
if(l==r)
{
if(count(a[l])==d) t[p].cnt=1,t[p].oor=t[p].aand=a[l];
return ;
}
build(ls,l,mid,d),build(rs,mid+1,r,d),t[p]=t[ls]+t[rs];
}
inline aa ask(int p,int l,int r,int vl,int vr)
{
if(vl<=l&&vr>=r) return t[p];
if(vr<=mid) return ask(ls,l,mid,vl,vr);
if(vl>mid) return ask(rs,mid+1,r,vl,vr);
return ask(ls,l,mid,vl,vr)+ask(rs,mid+1,r,vl,vr);
}
}T[35];
signed main()
{
freopen("peace.in","r",stdin),freopen("peace.out","w",stdout);
read(n,m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=0;i<=30;i++) T[i].build(1,1,n,i);
for(int l,r;m;m--)
{
read(l,r); aa pos[35],pre[35],suf[35]; bool flag=0;
for(int i=0;i<=30;i++) pos[i]=pre[i]=suf[i]=T[i].ask(1,1,n,l,r);
for(int i=1;i<=30;i++) pre[i]=pre[i-1]+pos[i];
for(int i=29;~i;i--) suf[i]=suf[i+1]+pos[i];
for(int i=0;i<=29;i++) flag|=(pre[i].cnt&&suf[i+1].cnt&&pre[i].oor==suf[i+1].aand);
for(int i=0;i<=30;i++) flag|=(pos[i].cnt>1&&pos[i].oor==pos[i].aand&&pre[i].oor==suf[i].aand);
puts(flag?"YES":"NO");
}
}
T3 摆烂合唱
需要知道什么是表达式树,然后就没有然后了,\(f_{x,0/1}\) 表示 \(x\) 为 \(0/1\) 概率,显然这两个概率加起来为 \(1\)。
- 异或:\(f_{x,0}=f_{ls,0}\times f_{rs,0}+f_{ls,1}\times f_{rs,1},f_{x,1}=1-f_{x,0}\)。
- 或:\(f_{x,0}=f_{ls,0}\times f_{rs,0},f_{x,1}=1-f_{x,0}\)。
- 与:\(f_{x,1}=f_{ls,1}\times f_{rs,1},f_{x,0}=1-f_{x,1}\)。
然后再遍历一遍输出即可:
- 异或:不管相邻项选什么此时填 \(0/1\) 答案都不同。
- 或:相邻项选 \(0\),则此时填 \(0/1\) 答案不同。
- 与:相邻项选 \(1\),则此时填 \(0/1\) 答案不同。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=4e5+10,P=998244353,inv=499122177;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,pos,tot,ls[N],rs[N],f[N][2]; char s[N],t[N];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
inline int dfs()
{
int x=++tot; if(s[++pos]=='x') return t[x]='x',f[x][0]=f[x][1]=inv,x;
ls[x]=dfs(),t[x]=s[++pos],rs[x]=dfs(),pos++;
switch(t[x])
{
case '^':
f[x][0]=mod(1ll*f[ls[x]][0]*f[rs[x]][0]%P,1ll*f[ls[x]][1]*f[rs[x]][1]%P);
f[x][1]=P+1-f[x][0]; break;
case '|':
f[x][0]=1ll*f[ls[x]][0]*f[rs[x]][0]%P;
f[x][1]=P+1-f[x][0]; break;
case '&':
f[x][1]=1ll*f[ls[x]][1]*f[rs[x]][1]%P;
f[x][0]=P+1-f[x][1]; break;
}
return x;
}
inline void print(int x,int ans)
{
if(t[x]=='x') return write(ans),puts(""),void();
switch(t[x])
{
case '^': print(ls[x],ans),print(rs[x],ans); break;
case '|':
print(ls[x],1ll*ans*f[rs[x]][0]%P);
print(rs[x],1ll*ans*f[ls[x]][0]%P); break;
case '&':
print(ls[x],1ll*ans*f[rs[x]][1]%P);
print(rs[x],1ll*ans*f[ls[x]][1]%P); break;
}
}
signed main()
{
freopen("binary.in","r",stdin),freopen("binary.out","w",stdout);
read(n),scanf("%s",s+1),dfs(),print(1,1);
}
T4 对称旅行者
有这题?
标签:20,rs,int,void,多校,read,ls,inline,NOIP2024 From: https://www.cnblogs.com/Charlieljk/p/18543602