省选模拟46
呵呵呵呵,我今天又一次被嘲讽了......一个月以内第三次被波波嘲讽eee
我菜,我菜废了,我菜到家了,啥也不会,啥也不是,完蛋玩意
今天的题确实是在考场上一点思路都没有,甚至板子一般的T1,没学过...
第二题可以看出和LCT有关,然而不会用,只想着能不能多骗几分
第三题确实想过树的计数,矩阵树定理嘛,然而想到是个森林就跑路了
T1 星际广播
二维dp显然,然而我自作聪明搞没了
发现这个非常的符合wqs二分的样子,有一个东西有最大的限制,并且是越多越优
还符合条件是个凸包,于是这个是wqs二分的板子,没想到吧
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e6+5;
int n,m,ll,col[N];
char s[N];
int ans;
pair<int,double> dp[N];
bool jud(double c,int co){
fo(i,1,n)dp[i]=make_pair(0,1e15);
dp[0]=make_pair(0,0);
fo(i,1,n){
if(dp[i-1].second+(col[i]!=co)<=dp[i].second){
dp[i]=dp[i-1];dp[i].second+=(col[i]!=co);
}
if(i>=ll){
if(dp[i-ll].second+c<=dp[i].second){
dp[i]=dp[i-ll];
dp[i].first+=1;
dp[i].second+=c;
}
}
}
return dp[n].first<=m;
}
int sol(int co){
double l=0,r=1e3,mid;
while(r-l>1e-8){
mid=(l+r)/2;
if(jud(mid,co))r=mid;
else l=mid;
}
jud(l,co);
return dp[n].second-l*m+0.5;
}
signed main(){
freopen("radio.in","r",stdin);
freopen("radio.out","w",stdout);
n=read();m=read();ll=read();
scanf("%s",s+1);
fo(i,1,n){
if(s[i]=='R')col[i]=0;
else if(s[i]=='B')col[i]=1;
else col[i]=2;
}
ans=min(sol(0),min(sol(1),sol(2)));
printf("%d",ans);
return 0;
}
T2 星际航道
发现一颗LCT可以维护边权不断变小的最小生成树,然后我祭了
考虑为什么给你一个网格图,很常见的对偶图
画出来之后发现,边集可以恰好划分成两个集合,一个是原图的最小生成树,一个是对偶图的最大生成树
于是我们就可以用两个LCT一个维护最小生成树,一个维护最大生成树
AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int n,m,cid,q,typ;ll lstans;
void decode(char ch,int &x,int &y,int &w) {
if(!typ)return ;
static int mask = 0xfffff;
w=(int)((w ^ lstans) & mask);
if(ch=='-')x=(x+lstans-1)%n+1,y=(y+lstans-1)%(m-1)+1;
if(ch=='|')x=(x+lstans-1)%(n-1)+1,y=(y+lstans-1)%m+1;
}
vector<int> id[N];
struct E{
int x,y,w;
bool operator < (E a)const{
if(w!=a.w)return w<a.w;
if(x!=a.x)return x<a.x;
return y<a.y;
}
}e[N*2],d[N*2];
int f[N*2];
bool com(int x,int y){
if(e[x].w!=e[y].w)return e[x].w<e[y].w;
if(e[x].x!=e[y].x)return e[x].x<e[y].x;
return e[x].y<e[y].y;
}
int cie,bl[N*2];
map<pair<int,int>,int> mp;
struct LCTMIN{
struct POT{
int son[2],fa;
int mx,ps,vl;bool rev;
}tr[N*3];
void init(){fo(i,0,cid)tr[i].vl=0;}
void pushup(int x){
tr[x].mx=max(tr[x].vl,max(tr[tr[x].son[0]].mx,tr[tr[x].son[1]].mx));
if(tr[x].mx==tr[x].vl)tr[x].ps=x;
else if(tr[x].mx==tr[tr[x].son[0]].mx)tr[x].ps=tr[tr[x].son[0]].ps;
else tr[x].ps=tr[tr[x].son[1]].ps;
return ;
}
void pushr(int x){
swap(tr[x].son[0],tr[x].son[1]);
tr[x].rev^=1;
}
void pushdown(int x){
if(!tr[x].rev)return ;
if(tr[x].son[0])pushr(tr[x].son[0]);
if(tr[x].son[1])pushr(tr[x].son[1]);
tr[x].rev=0;return ;
}
bool nroot(int x){return x==tr[tr[x].fa].son[0]||x==tr[tr[x].fa].son[1];}
int get(int x){return x==tr[tr[x].fa].son[1];}
void rotate(int x){
int y=tr[x].fa,z=tr[y].fa;
int xpos=get(x),ypos=get(y);
if(nroot(y))tr[z].son[ypos]=x;
tr[x].fa=z;tr[y].fa=x;
tr[y].son[xpos]=tr[x].son[xpos^1];
tr[tr[x].son[xpos^1]].fa=y;
tr[x].son[xpos^1]=y;
pushup(y);return ;
}
int pth[N],pt;
void splay(int x){
int now=x;pth[++pt]=now;
while(nroot(now))pth[++pt]=now=tr[now].fa;
while(pt)pushdown(pth[pt--]);
while(nroot(x)){
int y=tr[x].fa,z=tr[y].fa;
int xpos=get(x),ypos=get(y);
if(nroot(y)){
if(xpos==ypos)rotate(y);
else rotate(x);
}rotate(x);
}pushup(x);return ;
}
void access(int x){
for(int y=0;x;y=x,x=tr[x].fa){
splay(x);tr[x].son[1]=y;pushup(x);
}
}
void makert(int x){
access(x);splay(x);pushr(x);
}
int findrt(int x){
access(x);splay(x);
while(tr[x].son[0])pushdown(x),x=tr[x].son[0];
splay(x);return x;
}
void split(int x,int y){
makert(x);access(y);splay(y);
}
bool link(int x,int y){
makert(x);
if(findrt(y)==x)return false;
tr[x].fa=y;return true;
}
bool lian(int x,int y,int z){
return link(x,z)&&link(z,y);
}
bool cut(int x,int y){
makert(x);
if(findrt(y)!=x||tr[y].fa!=x||tr[y].son[0])return false;
tr[x].son[1]=tr[y].fa=0;pushup(x);
return true;
}
bool duan(int x,int y,int z){
return cut(x,z)&&cut(z,y);
}
bool inone(int x,int y){
return findrt(x)==findrt(y);
}
void change(int x,int v){
makert(x);tr[x].vl=v;pushup(x);
}
}lctmin;
struct LCTMAX{
struct POT{
int son[2],fa;
int mx,ps,vl;bool rev;
}tr[N*3];
void init(){fo(i,0,cid)tr[i].vl=tr[i].mx=inf;}
void pushup(int x){
tr[x].mx=min(tr[x].vl,min(tr[tr[x].son[0]].mx,tr[tr[x].son[1]].mx));
if(tr[x].mx==tr[x].vl)tr[x].ps=x;
else if(tr[x].mx==tr[tr[x].son[0]].mx)tr[x].ps=tr[tr[x].son[0]].ps;
else tr[x].ps=tr[tr[x].son[1]].ps;
// if(tr[x].ps==0)cerr<<x<<" "<<tr[x].son[0]<<" "<<tr[x].son[1]<<" "<<tr[x].vl<<" "<<tr[x].mx<<endl;
return ;
}
void pushr(int x){
swap(tr[x].son[0],tr[x].son[1]);
tr[x].rev^=1;
}
void pushdown(int x){
if(!tr[x].rev)return ;
if(tr[x].son[0])pushr(tr[x].son[0]);
if(tr[x].son[1])pushr(tr[x].son[1]);
tr[x].rev=0;return ;
}
bool nroot(int x){return x==tr[tr[x].fa].son[0]||x==tr[tr[x].fa].son[1];}
int get(int x){return x==tr[tr[x].fa].son[1];}
void rotate(int x){
int y=tr[x].fa,z=tr[y].fa;
int xpos=get(x),ypos=get(y);
if(nroot(y))tr[z].son[ypos]=x;
tr[x].fa=z;tr[y].fa=x;
tr[y].son[xpos]=tr[x].son[xpos^1];
tr[tr[x].son[xpos^1]].fa=y;
tr[x].son[xpos^1]=y;
pushup(y);return ;
}
int pth[N],pt;
void splay(int x){
int now=x;pth[++pt]=now;
while(nroot(now))pth[++pt]=now=tr[now].fa;
while(pt)pushdown(pth[pt--]);
while(nroot(x)){
int y=tr[x].fa,z=tr[y].fa;
int xpos=get(x),ypos=get(y);
if(nroot(y)){
if(xpos==ypos)rotate(y);
else rotate(x);
}rotate(x);
}pushup(x);return ;
}
void access(int x){
for(int y=0;x;y=x,x=tr[x].fa){
splay(x);tr[x].son[1]=y;pushup(x);
}
}
void makert(int x){
access(x);splay(x);pushr(x);
}
int findrt(int x){
access(x);splay(x);
while(tr[x].son[0])pushdown(x),x=tr[x].son[0];
splay(x);return x;
}
void split(int x,int y){
makert(x);access(y);splay(y);
}
bool link(int x,int y){
makert(x);
if(findrt(y)==x)return false;
tr[x].fa=y;return true;
}
bool lian(int x,int y,int z){
return link(x,z)&&link(z,y);
}
bool cut(int x,int y){
makert(x);
if(findrt(y)!=x||tr[y].fa!=x||tr[y].son[0])return false;
tr[x].son[1]=tr[y].fa=0;pushup(x);
return true;
}
bool duan(int x,int y,int z){
return cut(x,z)&&cut(z,y);
}
bool inone(int x,int y){
return findrt(x)==findrt(y);
}
void change(int x,int v){
makert(x);tr[x].vl=v;pushup(x);
}
}lctmax;
signed main(){
freopen("channel.in","r",stdin);
freopen("channel.out","w",stdout);
typ=read();
n=read();m=read();q=read();
id[0].resize(m+2);
fo(i,1,n){
id[i].resize(m+2);
fo(j,1,m)id[i][j]=++cid;
}cid++;
fo(i,0,m)id[0][i]=cid;
fo(i,1,n)id[i][0]=cid;
fo(i,1,n)fo(j,1,m){
if(j+1<=m){
mp[make_pair(id[i][j],id[i][j+1])]=++cie;
e[cie]=E{id[i][j],id[i][j+1],0};
int x=id[i][j],y=id[i-1][j];
if(i==n)x=cid;if(x>y)swap(x,y);
d[cie]=E{x,y,0};
}
if(i+1<=n){
mp[make_pair(id[i][j],id[i+1][j])]=++cie;
e[cie]=E{id[i][j],id[i+1][j],0};
int x=id[i][j],y=id[i][j-1];
if(j==m)x=cid;if(x>y)swap(x,y);
d[cie]=E{x,y,0};
}
}
lctmin.init();lctmax.init();
fo(i,1,cie)f[i]=i;sort(f+1,f+cie+1,com);
fo(i,1,cie){
int x=f[i];
if(lctmin.inone(e[x].x,e[x].y)){
lctmax.lian(d[x].x,d[x].y,x+cid);
bl[x]=1;
}
else {
lctmin.lian(e[x].x,e[x].y,x+cid);
bl[x]=0;
}
}
while(q--){
char tp[3];scanf("%s",tp+1);
int x=read(),y=read(),w=read();
decode(tp[1],x,y,w);int ide;
if(tp[1]=='-')ide=mp[make_pair(id[x][y],id[x][y+1])];
else ide=mp[make_pair(id[x][y],id[x+1][y])];
if(w>=e[ide].w){
if(bl[ide]==1){
e[ide].w=d[ide].w=w;
lctmin.change(ide+cid,w);
lctmax.change(ide+cid,w);
}
else {
lstans+=w-e[ide].w;
e[ide].w=d[ide].w=w;
lctmin.change(ide+cid,w);
lctmax.change(ide+cid,w);
lctmax.split(d[ide].x,d[ide].y);
int mn=lctmax.tr[d[ide].y].mx,ps=lctmax.tr[d[ide].y].ps-cid;
if(mn<w){
lctmax.duan(d[ps].x,d[ps].y,ps+cid);
lctmin.duan(e[ide].x,e[ide].y,ide+cid);
lctmax.lian(d[ide].x,d[ide].y,ide+cid);
lctmin.lian(e[ps].x,e[ps].y,ps+cid);
bl[ps]=0;bl[ide]=1;
lstans+=e[ps].w-e[ide].w;
}
}
}
else {
if(bl[ide]==0){
lstans+=w-e[ide].w;
e[ide].w=d[ide].w=w;
lctmin.change(ide+cid,w);
lctmax.change(ide+cid,w);
}
else {
// cerr<<"SB"<<endl;
e[ide].w=d[ide].w=w;
lctmin.change(ide+cid,w);
lctmax.change(ide+cid,w);
lctmin.split(e[ide].x,e[ide].y);
int mx=lctmin.tr[e[ide].y].mx,ps=lctmin.tr[e[ide].y].ps-cid;
if(mx>w){
lctmin.duan(e[ps].x,e[ps].y,ps+cid);
lctmax.duan(d[ide].x,d[ide].y,ide+cid);
lctmin.lian(e[ide].x,e[ide].y,ide+cid);
lctmax.lian(d[ps].x,d[ps].y,ps+cid);
bl[ide]=0;bl[ps]=1;
lstans+=e[ide].w-e[ps].w;
}
}
}
// fo(i,1,cie)cerr<<bl[i]<<" ";cerr<<endl;
printf("%lld\n",lstans);
}
}
T3 星际联邦
于是矩阵树定理,加入一个n+1节点将所有的树连起来,变成一颗整树
发现是个循环矩阵,于是可以直接用循环矩阵的公式求行列式,配个多项式,直接DFT
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=(1<<20)+5;
const int mod=998244353;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int n,k,ans;
int a[N],af[N],w[N],len,lim;
void ntt(int *a,int lim){
fo(i,0,lim-1)if(af[i]>i)swap(a[i],a[af[i]]);
for(int d=1,t=lim>>1;d<lim;d<<=1,t>>=1)
for(int i=0;i<lim;i+=(d<<1))
fo(j,0,d-1){
int tmp=w[t*j]*a[i+j+d]%mod;
a[i+j+d]=(a[i+j]-tmp+mod)%mod;
a[i+j]=(a[i+j]+tmp)%mod;
}
}
signed main(){
freopen("federation.in","r",stdin);
freopen("federation.out","w",stdout);
len=k=read();lim=n=1<<k;
fo(i,1,n-1)a[i]=mod-read(),a[0]=(a[0]+a[i])%mod;
a[0]=(1+mod-a[0])%mod;
// for(lim=1,len=0;lim<=n;lim<<=1,len++);
fo(i,0,lim-1)af[i]=(af[i>>1]>>1)|((i&1)<<(len-1));
w[0]=1;w[1]=ksm(3,(mod-1)/lim);
fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
ntt(a,lim);ans=1;
fo(i,0,lim-1)ans=ans*a[i]%mod;
printf("%lld\n",ans);
return 0;
}
QQ:2953174821