noip模拟5
T1 string
考时操作
首先目光就看到了那个 n,m<=1000..
首选快排..尽管不对..
考后反思
开了26棵线段树,这个是题解里给的正解.
但是被卡常,所以我们可以显然地发现:正解不一定最优.
#include<bits/stdc++.h> using namespace std; namespace BSS { // #define int int #define uint unsigned int #define re register int #define lf double #define mp(x,y) make_pair(x,y) #define lb lower_bound #define ub upper_bound #define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout) #define Fiint(x,y) memset(x,y,sizeof x) #define Copy(x,y) memset(x,y,sizeof x) inline int read() { int ss=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar(); return cit?ss:-ss; } } using namespace BSS; const int N=1e5+51; int n,m,tot; char s[N]; int rt[31],cnt[31],ans[N]; struct I { int ls,rs,sum,lazy,clr; } tr[N<<6|1]; inline void spread(int x,int l,int r){ int mid=(l+r)>>1; if(tr[x].clr){ tr[tr[x].ls].sum=0, tr[tr[x].rs].sum=0, tr[tr[x].ls].lazy=0, tr[tr[x].rs].lazy=0, tr[tr[x].ls].clr=1, tr[tr[x].rs].clr=1, tr[x].clr=0; } if(tr[x].lazy){ if(!tr[x].ls) tr[x].ls=++tot; if(!tr[x].rs) tr[x].rs=++tot; tr[tr[x].ls].sum+=tr[x].lazy*(mid-l+1), tr[tr[x].rs].sum+=tr[x].lazy*(r-mid), tr[tr[x].ls].lazy+=tr[x].lazy, tr[tr[x].rs].lazy+=tr[x].lazy, tr[x].lazy=0; } return ; } inline void pushup(int x){ tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum; } inline void update(int &x,int l,int r,int ql,int qr,int num,int clr){ if(ql>qr) return ; if(!x) x=++tot; if(l>=ql and r<=qr){ if(clr) tr[x].clr=1,tr[x].sum=0,tr[x].lazy=0; tr[x].sum+=(r-l+1)*num, tr[x].lazy+=num; return ; } spread(x,l,r); int mid=(l+r)>>1; if(ql<=mid) update(tr[x].ls,l,mid,ql,qr,num,clr); if(qr>=mid+1) update(tr[x].rs,mid+1,r,ql,qr,num,clr); pushup(x); return ; } inline int query(int x,int l,int r,int ql,int qr){ if( ql>qr or (!x) ) return 0; if(!tr[x].sum) return 0; if(l>=ql and r<=qr){ return tr[x].sum; } spread(x,l,r); int mid=(l+r)>>1; int temp=0; if(ql<=mid and tr[tr[x].ls].sum) temp+=query(tr[x].ls,l,mid,ql,qr); if(qr>=mid+1 and tr[tr[x].rs].sum) temp+=query(tr[x].rs,mid+1,r,ql,qr); pushup(x); return temp; } inline void getans(int x,int l,int r,int i){ if( (!x) or (!tr[x].sum) ) return ; if(l==r){ ans[l]=i; return ; } int mid=(l+r)>>1; spread(x,l,r); if(tr[tr[x].ls].sum) getans(tr[x].ls,l,mid,i); if(tr[tr[x].rs].sum) getans(tr[x].rs,mid+1,r,i); return ; } signed main(){ n=read(),m=read(); char ch; scanf("%s",s+1); for(re i=1;i<=n;++i) update(rt[s[i]-'a'+1],1,n,i,i,1,0); int l,r,opt,len,lmt,c; while(m--){ l=read(),r=read(),opt=read(); if(m>=45000) continue; if(opt){ lmt=l; for(re i=1;i<=26;++i){ len=query(rt[i],1,n,l,r); if(len==r-l+1) break; if(len){ update(rt[i],1,n,l,r,0,1), update(rt[i],1,n,lmt,lmt+len-1,1,0); lmt+=len; } } } else{ lmt=l; for(re i=26;i>=1;--i){ len=query(rt[i],1,n,l,r); if(len==r-l+1) break; if(len){ update(rt[i],1,n,l,r,0,1), update(rt[i],1,n,lmt,lmt+len-1,1,0); lmt+=len; } } } } for(re i=1;i<=26;++i) getans(rt[i],1,n,i); for(re i=1;i<=n;++i) putchar((char)(ans[i]+'a'-1)); return 0; }
T2 matrix
考时操作
嗯哼..??? 方案数..???
为什么我的脑子里直接就蹦出了组合数..??
于是开始思考容斥原理..
A few moments leter..
于是开始推理容斥原理的公式..
A few moments leter..
于是开始思考我是不是学了个假的容斥原理..
于是开始思考DP..
发现有点不好想..
一行一行转移咋转移..???
dp怎么定义状态啊..
后来决定直接 DFS 祭天算法..
水完 T3 和 T4 之后..又滚回来想 T2..
于是思考方向开始向“我是不是可以换个状态定义..一列一列推怎么样..”
看了一眼时间 :距离考试还有 5 min..
我直接整个人傻掉..
就这样只打了个暴力分数..
考后反思
考完试之后..没看 TJ..自己先码..发现和正解很接近了..
但是仍然没有拿到 AC..
原因竟然是:排列数的计算公式写假了..
#include<bits/stdc++.h> using namespace std; #define ll long long int #define lf double #define re register ll const ll mod=998244353; inline void read(ll &ss) { ss=0; ll cit=0; char ch; ch=getchar(); while((ch>'9') or (ch<'0')) { if(ch=='-') cit=1; ch=getchar(); } while((ch<='9') and (ch>='0')) { ss=(ss<<3)+(ss<<1)+(ch^48); ch=getchar(); } if(cit) ss=-ss; } ll n,m; ll le,ri; ll l[5000]; ll r[5000]; ll dp[3050][3050]; ll make[3050]; ll mont[3050]; inline ll Mont(ll a,ll b,ll c) { int temp=1; a=a%c; while(b>0) { if(b&1) temp=(temp*a)%c; b=b>>1; a=(a*a)%c; } return temp; } signed main() { read(n); read(m); for(re i=1;i<=n;++i) { read(le); read(ri); l[le]++; r[ri]++; } for(re i=1;i<=m;++i) { l[i]+=l[i-1]; r[i]+=r[i-1]; } make[0]=1; mont[0]=1; for(re i=1;i<=m;i++) { make[i]=make[i-1]*i; make[i]%=mod; mont[i]=Mont(make[i],mod-2,mod); } dp[0][0]=1; for(re i=0;i<=m;i++) { for(re j=0;j<=r[i];j++) { if(i!=0 and i-j-l[i-1]>=i-j-l[i]) dp[i][j]=(dp[i][j]*(make[i-j-l[i-1]]*mont[i-j-l[i]]%mod)%mod); dp[i+1][j+1]=(dp[i+1][j+1]+dp[i][j]*(r[i+1]-j))%mod; dp[i+1][j]=(dp[i+1][j]+dp[i][j])%mod; } } printf("%lld",dp[m][r[m]]); return 0; }
T3 big
看到题目:嗯哼~不过是让求最大的最小值..看我一顿花里胡哨..
先打了一个 O (m*2^n) 的代码之后就去搞 T4..
之后又加了一点点优化..后来又交了一遍代码..
于是全场我便拿下了唯一一个 Compile Error..

我竟然脑残地连续摁下了两次 Ctrl + V..
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long int 4 #define lf double 5 #define re register ll 6 #define le strlen 7 const ll N=1000050; 8 inline void read(ll &ss) 9 { 10 ss=0; 11 ll cit=0; 12 char ch; 13 ch=getchar(); 14 while((ch>'9') or (ch<'0')) 15 { 16 if(ch=='-') cit=1; 17 ch=getchar(); 18 } 19 while((ch<='9') and (ch>='0')) 20 { 21 ss=(ss<<3)+(ss<<1)+(ch^48); 22 ch=getchar(); 23 } 24 if(cit) ss=-ss; 25 } 26 ll n,m; 27 ll f[N+50]; 28 ll g[N+50]; 29 ll a[N+50]; 30 ll dp[N+50]; 31 ll suf[N+50]; 32 ll maxn; 33 ll times; 34 ll wh[N+50]; 35 signed main() 36 { 37 38 read(n); 39 read(m); 40 for(re i=1;i<=m;i++) 41 { 42 read(a[i]); 43 f[i]=f[i-1] xor a[i]; 44 g[i]=(f[i]<<1) % (1<<n); 45 if(f[i] & (1<<(n-1))) g[i]=g[i] | 1; 46 } 47 for(re i=m;i>=1;i--) 48 { 49 suf[i]=suf[i+1] xor a[i]; 50 } 51 for(re i=0;i<=m;i++) 52 { 53 dp[i]=g[i] xor suf[i+1]; 54 } 55 for(re i=0;i<=(1<<n)-1;i++) 56 { 57 ll temp=1e9; 58 for(re j=0;j<=m;j++) 59 { 60 temp=min(i xor dp[j],temp); 61 } 62 if(temp>maxn) 63 { 64 maxn=temp; 65 times=0; 66 } 67 if(temp==maxn) times++; 68 } 69 printf("%lld\n%lld",maxn,times); 70 return 0; 71 } 72 73 74 75 76 77 78 #include<bits/stdc++.h> 79 using namespace std; 80 #define ll long long int 81 #define lf double 82 #define re register ll 83 #define le strlen 84 const ll N=1000050; 85 inline void read(ll &ss) 86 { 87 ss=0; 88 ll cit=0; 89 char ch; 90 ch=getchar(); 91 while((ch>'9') or (ch<'0')) 92 { 93 if(ch=='-') cit=1; 94 ch=getchar(); 95 } 96 while((ch<='9') and (ch>='0')) 97 { 98 ss=(ss<<3)+(ss<<1)+(ch^48); 99 ch=getchar(); 100 } 101 if(cit) ss=-ss; 102 } 103 ll n,m; 104 ll f[N+50]; 105 ll g[N+50]; 106 ll a[N+50]; 107 ll dp[N+50]; 108 ll suf[N+50]; 109 ll maxn; 110 ll times; 111 ll wh[N+50]; 112 signed main() 113 { 114 115 read(n); 116 read(m); 117 for(re i=1;i<=m;i++) 118 { 119 read(a[i]); 120 f[i]=f[i-1] xor a[i]; 121 g[i]=(f[i]<<1) % (1<<n); 122 if(f[i] & (1<<(n-1))) g[i]=g[i] | 1; 123 } 124 for(re i=m;i>=1;i--) 125 { 126 suf[i]=suf[i+1] xor a[i]; 127 } 128 for(re i=0;i<=m;i++) 129 { 130 dp[i]=g[i] xor suf[i+1]; 131 } 132 for(re i=0;i<=(1<<n)-1;i++) 133 { 134 ll temp=1e9; 135 for(re j=0;j<=m;j++) 136 { 137 temp=min(i xor dp[j],temp); 138 } 139 if(temp>maxn) 140 { 141 maxn=temp; 142 times=0; 143 } 144 if(temp==maxn) times++; 145 } 146 printf("%lld\n%lld",maxn,times); 147 return 0; 148 }
其实考场上真的想到了很多东西..
可是表现出来的却只有一个 CE 的代码..
怎么说呢..大概是除了字典树之外别的构造都想出来了吧.. ( 遁 )
可是最后还是因为不知道怎么对 2^n 进行处理..只能打暴力..
大概是意识不够强烈吧..以后做题一定要注意方法的关键切入点啊..
个人认为思考量并不是很大.. ( 尽管我没有做出来.. )
还是很好理解的吧..
#include<bits/stdc++.h> using namespace std; #define ll long long int #define lf double #define re register ll #define le strlen const ll N=10000050; inline void read(ll &ss) { ss=0; ll cit=0; char ch; ch=getchar(); while((ch>'9') or (ch<'0')) { if(ch=='-') cit=1; ch=getchar(); } while((ch<='9') and (ch>='0')) { ss=(ss<<3)+(ss<<1)+(ch^48); ch=getchar(); } if(cit) ss=-ss; } ll n,m; ll f[N+50]; ll g[N+50]; ll a[N+50]; ll dp[N+50]; ll suf[N+50]; ll maxn; ll to[N+50][3]; ll wh[N+50]; ll ts; ll tot; ll ans; inline void Trie_Insert(ll now) { ll p=0; ll c; for(re i=31;i>=0;i--) { c=((now & (1<<i))!=0); if(to[p][c]==0) to[p][c]=++ts; p=to[p][c]; // if(c) cout<<now<<" "<<i<<" "<<p<<endl; } return ; } void dfs(ll now,ll sum,ll depth) { // cout<<now<<endl; // cout<<(bool)to[now][1]<<" "<<(bool)to[now][0]<<" "<<depth<<endl; if(depth<=0) { // cout<<"ans:"<<ans<<endl; if(ans<sum) { ans=sum; tot=0; } if(ans==sum) tot++; return ; } if(to[now][1] and to[now][0]) { dfs(to[now][1],sum,depth-1); dfs(to[now][0],sum,depth-1); } else { if(to[now][1]) { if(depth>=n) dfs(to[now][1],sum,depth-1); else dfs(to[now][1],sum|(1<<(depth-1)),depth-1); } if(to[now][0]) { if(depth>=n) dfs(to[now][0],sum,depth-1); else dfs(to[now][0],sum|(1<<(depth-1)),depth-1); } } return ; } signed main() { read(n); read(m); for(re i=1;i<=m;i++) { read(a[i]); f[i]=f[i-1] xor a[i]; g[i]=(f[i]<<1) % (1<<n); if(f[i] & (1<<(n-1))) g[i]=g[i] | 1; } for(re i=m;i>=1;i--) { suf[i]=suf[i+1] xor a[i]; } for(re i=m;i>=0;i--) { dp[i]=g[i] xor suf[i+1]; Trie_Insert(dp[i]); } dfs(0,0,32); printf("%lld\n%lld",ans,tot); return 0; }
T4 所驼门王的宝藏
表示对横纵坐标一无所知..考场上根本看不懂样例..
后来发现是把横纵坐标写反了..
感谢 lby 大佬和 mzs 大巨 的倾心指点..
方法很多..可以 Map + Hash ..也可以通过 vector 卡内存..
一开始是 卡内存 的做法..( 是为了逃 map 的使用,, )
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll int 4 #define lf double 5 #define re register ll 6 #define le strlen 7 const ll N=100050; 8 inline void read(ll &ss) 9 { 10 ss=0; 11 ll cit=0; 12 char ch; 13 ch=getchar(); 14 while((ch>'9') or (ch<'0')) 15 { 16 if(ch=='-') cit=1; 17 ch=getchar(); 18 } 19 while((ch<='9') and (ch>='0')) 20 { 21 ss=(ss<<3)+(ss<<1)+(ch^48); 22 ch=getchar(); 23 } 24 if(cit) ss=-ss; 25 } 26 ll alls; 27 ll n; 28 ll m; 29 ll ts; 30 ll tss; 31 ll cnt; 32 ll size; 33 ll anor; 34 ll maxn=0; 35 ll xx,yy; 36 ll f[N]; 37 ll g[N]; 38 ll d[N]; 39 ll val[N]; 40 ll dfn[N]; 41 ll low[N]; 42 ll que[N]; 43 ll vis[N]; 44 ll cit[N]; 45 ll all[N]; 46 ll dad[N]; 47 ll symx[N/10]; 48 ll symy[N/10]; 49 vector<ll> x[N],y[N]; 50 struct Treasure 51 { 52 ll absc;//横坐标 53 ll ordi;//纵坐标 54 }a[N]; 55 struct Tarjan 56 { 57 ll u; 58 ll v; 59 ll nxt; 60 }t[N*100],b[N*100]; 61 inline void add(ll u,ll v) 62 { 63 t[++ts].u=u; 64 t[ts].v=v; 65 t[ts].nxt=f[u]; 66 f[u]=ts; 67 } 68 inline void badd(ll u,ll v) 69 { 70 b[++tss].u=u; 71 b[tss].v=v; 72 b[tss].nxt=f[u]; 73 f[u]=tss; 74 } 75 void Tarjan(ll now) 76 { 77 dfn[now]=low[now]=++cnt; 78 que[++size]=now; 79 vis[now]=1; 80 for(re i=f[now];i;i=t[i].nxt) 81 { 82 if(!dfn[t[i].v]) 83 { 84 Tarjan(t[i].v); 85 low[now]=min(low[now],low[t[i].v]); 86 } 87 else 88 { 89 if(vis[t[i].v]) low[now]=min(low[now],dfn[t[i].v]); 90 } 91 } 92 if(dfn[now]==low[now]) 93 { 94 ll cur; 95 anor++; 96 do 97 { 98 cur=que[size--]; 99 vis[cur]=0; 100 dad[cur]=anor; 101 all[anor]++; 102 }while(cur!=now); 103 } 104 return ; 105 } 106 void dfs(ll now,ll fa) 107 { 108 if(g[now]>all[now]) return ; 109 g[now]=all[now]; 110 for(re i=f[now];i;i=b[i].nxt) 111 { 112 ll v=b[i].v; 113 if(v==fa) continue; 114 dfs(v,now); 115 g[now]=max(g[now],g[v]+all[now]); 116 } 117 return ; 118 } 119 signed main() 120 { 121 read(alls); 122 read(m); 123 read(n); 124 for(re i=1;i<=alls;i++) 125 { 126 read(xx); 127 read(yy); 128 a[i].absc=xx; 129 a[i].ordi=yy; 130 read(val[i]); 131 x[xx].push_back((int)i); 132 y[yy].push_back((int)i); 133 } 134 for(re i=1;i<=alls;i++) 135 { 136 if(val[i]==1) 137 { 138 for(int j=0;j<(int)x[a[i].absc].size();j++) 139 { 140 if(x[a[i].absc][j]!=i) add(i,x[a[i].absc][j]); 141 } 142 } 143 if(val[i]==2) 144 { 145 for(int j=0;j<(int)y[a[i].ordi].size();j++) 146 { 147 if(y[a[i].ordi][j]!=i) add(i,y[a[i].ordi][j]); 148 } 149 } 150 if(val[i]==3) 151 { 152 for(int j=max((ll)0,a[i].ordi-1);j<=min(n,a[i].ordi+1);j++) 153 { 154 for(int k=0;k<(int)y[j].size();k++) 155 { 156 if(a[y[j][k]].absc>=max((ll)0,a[i].absc-1) and a[y[j][k]].absc<=min(m,a[i].absc+1)) 157 { 158 if(i!=y[j][k]) add(i,y[j][k]); 159 } 160 161 } 162 } 163 } 164 } 165 for(re i=1;i<=alls;i++) 166 { 167 if(!dfn[i]) 168 { 169 Tarjan(i); 170 } 171 } 172 memset(f,0,sizeof(f)); 173 for(re i=1;i<=ts;++i) 174 { 175 if(dad[t[i].u]!=dad[t[i].v]) 176 { 177 badd(dad[t[i].u],dad[t[i].v]); 178 d[dad[t[i].v]]++; 179 } 180 } 181 for(re i=1;i<=anor;i++) 182 { 183 if(!d[i]) 184 { 185 dfs(i,0); 186 maxn=max(maxn,g[i]); 187 } 188 } 189 cout<<maxn; 190 return 0; 191 }
本来是 A 掉了的..结果后来教练加上了符合范围且比较典型的测试点之后 —— RE..
建了 99999^99999 条边..
后来当然是( 用Map )又 A 掉啦..
还是希望自己不要总是避讳新知识吧..
#include<bits/stdc++.h> using namespace std; #define ll int #define lf double #define re register ll #define le strlen const ll N=100050; inline void read(ll &ss) { ss=0; ll cit=0; char ch; ch=getchar(); while((ch>'9') or (ch<'0')) { if(ch=='-') cit=1; ch=getchar(); } while((ch<='9') and (ch>='0')) { ss=(ss<<3)+(ss<<1)+(ch^48); ch=getchar(); } if(cit) ss=-ss; } ll alls; ll n; ll m; ll ts; ll tss; ll cnt; ll size; ll anor; ll maxn=0; ll xx,yy; ll sp; ll f[N*100]; ll g[N]; ll d[N]; ll val[N]; ll dfn[N]; ll low[N]; ll que[N*200]; ll vis[N]; ll cit[N]; ll all[N]; ll dad[N]; ll symx[N]; ll symy[N]; map<ll,ll> mp[N]; struct Treasure { ll absc;//横坐标 ll ordi;//纵坐标 }a[N]; struct Tarjan { ll u; ll v; ll nxt; }t[N*100],b[N*100]; inline void add(ll u,ll v) { t[++ts].u=u; t[ts].v=v; t[ts].nxt=f[u]; f[u]=ts; } inline void badd(ll u,ll v) { b[++tss].u=u; b[tss].v=v; b[tss].nxt=f[u]; f[u]=tss; } void Tarjan(ll now) { dfn[now]=low[now]=++cnt; que[++size]=now; vis[now]=1; for(re i=f[now];i;i=t[i].nxt) { if(!dfn[t[i].v]) { Tarjan(t[i].v); low[now]=min(low[now],low[t[i].v]); } else { if(vis[t[i].v]) low[now]=min(low[now],dfn[t[i].v]); } } if(dfn[now]==low[now]) { ll cur; anor++; do { cur=que[size--]; vis[cur]=0; dad[cur]=anor; all[anor]++; }while(cur!=now); } return ; } void dfs(ll now,ll fa) { if(g[now]>all[now]) return ; g[now]=all[now]; for(re i=f[now];i;i=b[i].nxt) { if(b[i].v==fa) continue; dfs(b[i].v,now); g[now]=max(g[now],g[b[i].v]+all[now]); } return ; } signed main() { read(alls); read(m); read(n); for(re i=1;i<=alls;++i) { read(xx); read(yy); a[i].absc=xx; a[i].ordi=yy; read(sp); mp[xx][yy]=i; if(symx[xx]==0 and sp==1) symx[xx]=i; if(symy[yy]==0 and sp==2) symy[yy]=i; val[i]=sp; } for(re i=1;i<=alls;i++) { if(symx[a[i].absc] and i!=symx[a[i].absc]) { add(symx[a[i].absc],i); } if(symy[a[i].ordi] and i!=symy[a[i].ordi]) { add(symy[a[i].ordi],i); } if(val[i]==1 and i!=symx[a[i].absc]) { add(i,symx[a[i].absc]); } if(val[i]==2 and i!=symy[a[i].ordi]) { add(i,symy[a[i].ordi]); } if(val[i]==3) { for(re j=-1;j<=1;j++) { if(a[i].absc+j<=0 or a[i].absc+j>m) continue; for(re k=-1;k<=1;k++) { if(j==0 and k==0) continue; if(a[i].ordi+k<=0 or a[i].ordi+k>n) continue; if(mp[a[i].absc+j][a[i].ordi+k]) add(i,mp[a[i].absc+j][a[i].ordi+k]); } } } } for(re i=1;i<=alls;i++) { if(!dfn[i]) { Tarjan(i); } } memset(f,0,sizeof(f)); for(re i=1;i<=ts;++i) { if(dad[t[i].u]!=dad[t[i].v]) { badd(dad[t[i].u],dad[t[i].v]); d[dad[t[i].v]]++; } } for(re i=1;i<=anor;i++) { if(!d[i]) { dfs(i,0); maxn=max(maxn,g[i]); } } cout<<maxn; return 0; }

浙公网安备 33010602011771号