省选模拟18
不能说是挂分,只能说是菜,思考问题相当的不严谨!!
考试之前zxb告诉我,别人考过这个,全场只有一个人切掉了第一题
可能是受影响了吧,以后要避免
第一题,看了将近三个小时,于是只会暴力分
第二题,第一次看出来了绝顶聪明的人的策略,其实是题面给提示了
第三题,看了十分钟题面然后考试就结束了......
T1 货币
暴力就是尺取法......
考场上想到了启发式合并维护前趋,然而并不知道怎么用??!!
也想到了单调性,甚至想到了拆区间的次数有限!!!
然后就没了,发现用不上,原因是考场上拆区间的时候用的是枚举
合理利用线段树二分,哈哈哈,然后就能切掉了,注意写的时候小心点!!很麻烦
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*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e5+5;
const int inf=0x3f3f3f3f;
struct D{
int fa[N],siz[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
}d;
int n,q,typ,ans,lans;
int pre[N],rig[N];
struct XDS{
#define ls x<<1
#define rs x<<1|1
int mif[N*4],mnf[N*4],mxf[N*4],taf[N*4];//f
int mip[N*4],mos[N*4];//pre
int mnr[N*4];//question range
void pushup(int x){
mnr[x]=min(mnr[ls],mnr[rs]);
mif[x]=min(mif[ls],mif[rs]);
mxf[x]=max(mxf[ls],mxf[rs]);
mnf[x]=min(mnf[ls],mnf[rs]);
if(mip[ls]>mip[rs])mip[x]=mip[rs],mos[x]=mos[rs];
else mip[x]=mip[ls],mos[x]=mos[ls];
}
void pushdown(int x,int l,int r){
int mid=l+r>>1;
taf[ls]=taf[x];mif[ls]=taf[x]-mid+1;
mnf[ls]=mxf[ls]=taf[x];
taf[rs]=taf[x];mif[rs]=taf[x]-r+1;
mnf[rs]=mxf[rs]=taf[x];
taf[x]=0;
}
void build(int x,int l,int r){
if(l==r){
mif[x]=n-l+1,mip[x]=0,mos[x]=l,mnr[x]=l;
mnf[x]=mxf[x]=n;return ;
}
int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);pushup(x);
}
void insf(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){taf[x]=v;mif[x]=v-r+1;mnf[x]=mxf[x]=v;return ;}
int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
if(ql<=mid)insf(ls,l,mid,ql,qr,v);
if(qr>mid)insf(rs,mid+1,r,ql,qr,v);
pushup(x);
}
int queryf(int x,int l,int r,int ql,int qr){
//cerr<<x<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<mif[x]<<endl;
if(ql<=l&&r<=qr)return mif[x];
int mid=l+r>>1,ret=inf;if(taf[x])pushdown(x,l,r);
if(ql<=mid)ret=min(ret,queryf(ls,l,mid,ql,qr));
if(qr>mid)ret=min(ret,queryf(rs,mid+1,r,ql,qr));
pushup(x);return ret;
}
void insp(int x,int l,int r,int pos,int v){
if(l==r)return mip[x]=v,void();
int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
if(pos<=mid)insp(ls,l,mid,pos,v);
else insp(rs,mid+1,r,pos,v);
pushup(x);
}
int queryp(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return mos[x];
int mid=l+r>>1,ret=0;if(taf[x])pushdown(x,l,r);
if(ql<=mid)ret=queryp(ls,l,mid,ql,qr);
if(qr>mid){
int tmp=queryp(rs,mid+1,r,ql,qr);
if(!ret||pre[ret]>pre[tmp])ret=tmp;
}pushup(x);return ret;
}
void insr(int x,int l,int r,int pos,int v){
if(l==r)return mnr[x]=v,void();
int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
if(pos<=mid)insr(ls,l,mid,pos,v);
else insr(rs,mid+1,r,pos,v);
pushup(x);
}
int resl,resr;
void init_res(){resl=n+1;resr=0;}
void quf(int x,int l,int r,int v){
if(mxf[x]<v||mnf[x]>v)return ;
if(mnf[x]==v&&mxf[x]==v)return resl=min(resl,l),resr=max(resr,r),void();
int mid=l+r>>1;if(taf[x])pushdown(x,l,r);
if(mxf[ls]>=v)quf(ls,l,mid,v);
if(mnf[rs]<=v)quf(rs,mid+1,r,v);
pushup(x);
}
int qul(int x,int l,int r,int qr,int v){//left qr && min>=v
//cerr<<x<<" "<<l<<" "<<r<<" "<<qr<<" "<<v<<endl;
if(r<=qr){
if(mip[x]>=v)return l;
if(l==r)return l+1;
int mid=l+r>>1,ret;if(taf[x])pushdown(x,l,r);
if(mip[rs]>=v)ret=qul(ls,l,mid,qr,v);
else ret=qul(rs,mid+1,r,qr,v);
pushup(x);return ret;
}
int mid=l+r>>1,ret=0;if(taf[x])pushdown(x,l,r);
if(mid+1<=qr)ret=qul(rs,mid+1,r,qr,v);
if(ret==mid+1||ret==0)ret=qul(ls,l,mid,qr,v);
pushup(x);return ret;
}
#undef ls
#undef rs
}xds;
set<int> st[N];
void change(int now){
//cerr<<"now"<<" "<<now<<" "<<pre[now]<<endl;
xds.insp(1,1,n,now,pre[now]);
xds.init_res();xds.quf(1,1,n,now);
int l=xds.resl,r=min(pre[now],xds.resr);
//cerr<<"l"<<" "<<l<<" "<<r<<endl;
while(l<=r){
//cerr<<"S"<<l<<" "<<r<<" ";
int pos=xds.qul(1,1,n,now,l);
//cerr<<" "<<pos<<" ";
int p=xds.queryp(1,1,n,pos,now);
//cerr<<" "<<p<<" "<<pre[p]<<endl;
xds.insf(1,1,n,l,min(r,pre[p]),pos-1);
l=pre[p]+1;
}
//cerr<<"B"<<endl;
}
signed main(){
freopen("currency.in","r",stdin);
freopen("currency.out","w",stdout);
n=read();q=read();typ=read();ans=n;
fo(i,1,n){
pre[i]=0;st[i].insert(i);rig[i]=i;
d.fa[i]=i;d.siz[i]=1;
}
xds.build(1,1,n);
while(q--){
int x=(read()+typ*lans-1)%n+1,y=(read()+typ*lans-1)%n+1;
int fx=d.find(x),fy=d.find(y);
if(fx==fy){printf("%d\n",ans);continue;}
if(d.siz[fy]>d.siz[fx])swap(fy,fx);
d.fa[fy]=fx;d.siz[fx]+=d.siz[fy];
rig[fx]=max(rig[fx],rig[fy]);
xds.insr(1,1,n,fy,inf);xds.insr(1,1,n,fx,rig[fx]);
for(int i:st[fy]){
st[fx].insert(i);
set<int>::iterator it=st[fx].find(i);
if(it!=st[fx].begin()){
pre[i]=*prev(it);change(i);
}
else pre[i]=0;
if(next(it)!=st[fx].end()){
int now=*next(it);pre[now]=i;
change(now);
}
}st[fy].clear();
printf("%d\n",lans=ans=xds.queryf(1,1,n,1,xds.mnr[1]));
}
return 0;
}
T2 比赛
发现隔一个能选一个,于是就每次暴力修改
然后数据比较水,链长是log就过了,后来被yspm用一条链卡掉了
于是摇摆兵仔细观察了数据,发现这是一条链,判走了......
这都不是重点,重点是他判完之后,没有自己A掉,然后跑到我这里来忽悠我......
暴力碾标算
#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*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=3e6+5;
int n,q,a[N],ans;
int buc[N],du[N],dep[N];
set<int> win[N];
void dfs2(int x,int v){
if(!v)return ;dep[x]+=v;
if(dep[x]==v)win[(x-a[x]+n)%n].erase(x);
if(dep[x]==0)win[(x-a[x]+n)%n].insert(x);
if(a[x]<=x&&a[x])dfs2(x-a[x],(!dep[x])?1:(dep[x]==v?-1:0));
}
signed main(){
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
n=read();q=read();
fo(i,0,n-1)a[i]=read();
fu(i,n-1,0)if((!dep[i])&&a[i]<=i&&a[i])dep[i-a[i]]++;
fo(i,0,n-1)if(!dep[i])win[(i-a[i]+n)%n].insert(i);
if(win[0].size())ans=*win[0].begin();
else ans=0;
printf("%d\n",ans);
while(q--){
int x=read(),y=read();
if(a[x]<=x&&a[x]){
dfs2(x-a[x],!dep[x]?-1:0);
du[x-a[x]]--;
}
if(y<=x&&y){
dfs2(x-y,(!dep[x])?1:0);
du[x-y]++;
}
if(!dep[x])win[(x-a[x]+n)%n].erase(x),win[(x-y+n)%n].insert(x);
a[x]=y;
if(win[0].size())ans=*win[0].begin();
else ans=0;
printf("%d\n",ans);
}
return 0;
}
正解还没有打,是LCT
AC_code
T3 字符串
构造一个合法的AC自动机
如果有根了,那么我们需要判断这个根是否合法,可以将fail树上链接的两个点连向父亲的边用并查集缩起来!
然后直接构建自动机,这里构建方式就是爆跳fail,不然炸内存!!
剩下的就是观察性质了,。。。
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*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=3e5+5;
int n,ans[N],can;
struct D{
struct E{int to,nxt,id;}e[N*2];
int head[N],rp,fe[N],dep[N],fa[N];
void add_edg(int x,int y,int id){
e[++rp].to=y;e[rp].nxt=head[x];
e[rp].id=id;head[x]=rp;
}
}d1,d2;
int fai[N];
int find(int x){return fai[x]==x?x:fai[x]=find(fai[x]);}
void dfs(int x,int f){
d1.dep[x]=d1.dep[f]+1;d1.fa[x]=f;
for(int i=d1.head[x];i;i=d1.e[i].nxt){
int y=d1.e[i].to;
if(y==f)continue;
d1.fe[y]=d1.e[i].id;dfs(y,x);
}
}
void dfss(int x,int f){
d2.dep[x]=d2.dep[f]+1;d2.fa[x]=f;
for(int i=d2.head[x];i;i=d2.e[i].nxt){
int y=d2.e[i].to;
if(y==f)continue;dfss(y,x);
}
}
int buc[N],fail[N];
map<int,int> mp[N];
bool check(int rt){
fo(i,1,n-1)fai[i]=i;
dfs(rt,0);dfss(rt,0);can=0;
fo(x,1,n){fail[x]=0;
if(x==rt)continue;
for(int i=d2.head[x];i;i=d2.e[i].nxt){
int y=d2.e[i].to;
if(d1.dep[y]<d1.dep[x]){fail[x]=y;continue;}
int fx=find(d1.fe[x]),fy=find(d1.fe[y]);
if(fx==fy)continue;fai[fx]=fy;
}
if(!fail[x])return false;
}
fo(i,1,n-1)if(find(i)==i)ans[i]=++can,buc[can]=0;
queue<int> q;while(!q.empty())q.pop();
mp[rt].clear();
for(int i=d1.head[rt];i;i=d1.e[i].nxt){
int y=d1.e[i].to;q.push(y);
buc[ans[find(d1.e[i].id)]]++;
mp[rt][ans[find(d1.e[i].id)]]=y;
if(buc[ans[find(d1.e[i].id)]]>1)return false;
}
for(int i=d1.head[rt];i;i=d1.e[i].nxt)buc[ans[find(d1.e[i].id)]]--;
while(!q.empty()){
int x=q.front();q.pop();mp[x].clear();
for(int i=d1.head[x];i;i=d1.e[i].nxt){
int y=d1.e[i].to;
if(d1.dep[y]<d1.dep[x])continue;
if(d2.dep[x]<d2.dep[y]-1)return false;
buc[ans[find(d1.e[i].id)]]++;
mp[x][ans[find(d1.e[i].id)]]=y;
if(buc[ans[find(d1.e[i].id)]]>1)return false;
int now=x;q.push(y);
while(now!=rt&&mp[fail[now]].find(ans[find(d1.e[i].id)])==mp[fail[now]].end())now=fail[now];
if(now==rt&&fail[y]!=rt)return false;
if(now!=rt&&fail[y]!=mp[fail[now]][ans[find(d1.e[i].id)]])return false;
}
for(int i=d1.head[x];i;i=d1.e[i].nxt){
int y=d1.e[i].to;
if(d1.dep[y]<d1.dep[x])continue;
buc[ans[find(d1.e[i].id)]]--;
}
}
return true;
}
map<pair<int,int>,int> ed;
int du[N];bool vs[N];int ps[N];
signed main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
n=read();
fo(i,1,n-1){
int x=read(),y=read();
d1.add_edg(x,y,i);d1.add_edg(y,x,i);
ed.insert(make_pair(make_pair(min(x,y),max(x,y)),1));
}
fo(i,1,n-1){
int x=read(),y=read();
d2.add_edg(x,y,i);d2.add_edg(y,x,i);
if(ed.find(make_pair(min(x,y),max(x,y)))!=ed.end()){
du[x]++;du[y]++;vs[x]=vs[y]=true;
}
}
fo(i,1,n)if(du[i]>=3){check(i);printf("%d\n",i);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
fo(x,1,n)if(vs[x]){
for(int i=d1.head[x];i;i=d1.e[i].nxt){
int y=d1.e[i].to;
if(!vs[y]&&!ps[y]){
ps[y]=true;
for(int j=d2.head[y];j;j=d2.e[j].nxt){
int z=d2.e[j].to;
if(vs[z])if(check(z)){printf("%d\n",z);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
for(int k=d2.head[z];k;k=d2.e[k].nxt){
int w=d2.e[k].to;
if(vs[w])if(check(w)){printf("%d\n",w);fo(j,1,n-1)printf("%d ",ans[find(j)]);return 0;}
}
}
}
}
}
}
QQ:2953174821