暑假模擬15
\(T_A\) 串串
簡單字串題,考慮列舉迴文中心,雜湊維護,沒什麼思維量,但是不好調。
wang54321 有高階 manacher 做法,大家快去膜拜她。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+100;
const ll mod=1000001011;
const ll base=2333;
char s[N];
int n,m;
bool b[N];
ll x,y,ny,p[N];
ll qpow(ll res,ll t){
ll ans=1;
while(t){
if(t&1)ans=ans*res%mod;
res=res*res%mod;
t>>=1;
}
return ans;
}
int main()
{
scanf("%d",&n);
ny=qpow(base,mod-2);
p[0]=1;
for(int i=1;i<=1000000;i++){
p[i]=p[i-1]*base%mod;
}
while(n--){
scanf("%s",s+1);
m=strlen(s+1);
if(m==1){
puts("1");
continue;
}
for(int i=1;i<=m;i++){
b[i]=0;
}
x=y=0;
for(int i=m,len=0;i>=2;i--){
if(x==y){
if(i>m/2)b[i]=1;
else b[i]=b[i+len];
}
if(i-1>m/2){
y=(y+(s[i]-'a')*p[len])%mod;
if(i!=m){
x=((x-(s[i-1]-'a')*p[len-1])%mod+mod)%mod;
x=x*p[2]%mod;
x=(x+(s[i-len-1]-'a')*p[1])%mod;
}
x=(x+(s[i-len-2]-'a'))%mod;
len++;
}
else if(i-1==m/2){
x=0;
for(int j=i-2;j>=1;j--){
x=(x*base+s[j]-'a')%mod;
}
y=0;
for(int j=i;j<2*i-2;j++){
y=(y*base+s[j]-'a')%mod;
}
len=i-2;
}
else{
x=((x-(s[i-1]-'a')*p[len-1])%mod+mod)%mod;
if(i!=2){
y=((y-(s[i+len]-'a')-(s[i+len-1]-'a')*base)%mod+mod)%mod;
y=y*ny%mod*ny%mod;
y=(y+(s[i]-'a')*p[len-2])%mod;
}
len--;
}
}
for(int i=1;i<=m;i++){
if(b[i])printf("%d ",i);
}
puts("");
}
}
\(T_B\)排排
更簡單的結論題,容易發現以下結論:
-
當且僅當 \(P\) 嚴格遞增時,答案為 \(0\)
-
當且僅當存在一個 \(P_i=i\) 使得 \(P_1\dots P_i\) 是一個 \(1 \dots i\) 的排列,答案為 \(1\)
-
當且僅當 \(P_1=n,P_n=1\) ,答案為 \(3\)
-
其餘情況答案均為 \(2\)
\(T_C\)序序
難題,不會
\(T_D\)橋橋
好題,雖然我沒過,但我可以口胡。
首先將所有操作離線,分塊,設塊長為 \(T\) 。
對於每一塊,按照邊權降序排列 \(m\) 條邊,並按如下方式排列塊內操作:
修改按照出現順序降序,查詢按照重量降序排列,以後會有用。
對於每個查詢,沒有被修改的邊權大於當前詢問的邊可能會有貢獻,用並查集維護連通性。而被修改的邊,如果對當前詢問沒有影響,回到上一種情況,如果有影響,則只考慮最後一次修改這條邊的貢獻。每次改變詢問要求並查集可撤銷(不要路徑壓縮)。由於每個塊內操作並不多,暴力修改即可,保證複雜度正確,可能需要卡常。
還沒過題,程式碼莫名原因 \(WA\) 了,先貼上。
CODE
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
const int N=5e5+100;
int n,m,q,a,b,c,op,cnt,head[N];
int T,sum,lef[N],rig[N];
int f[N],siz[N],tot,p[N],ans[N];
bool vis[N],pd[N];
int dfn[N];
bool o[N];
struct query{
int op,x,y,id;
}t[N];
struct Bridge{
int from,to,wei,id;
}br[N];
bool cmp(query o,query p){
if(o.op==p.op){
if(o.op==2)return o.y>p.y;
else return o.id>p.id;
}
else return o.op<p.op;
}
bool cmp1(Bridge o,Bridge p){
return o.wei>p.wei;
}
int find(int x){
if(x==f[x])return x;
else return find(f[x]);
}
stack<pii>st;
inline void merge(int u,int v,bool flag){
int fx=find(u),fy=find(v);
if(fx==fy)return ;
tot++;
if(siz[fx]>siz[fy]){
if(flag){
st.push(mp(fy,fx));
}
f[fy]=fx;
siz[fx]+=siz[fy];
}
else{
if(flag){
st.push(mp(fx,fy));
}
f[fx]=fy;
siz[fy]+=siz[fx];
}
}
void solve(int l,int r,int x){
sort(br+1,br+m+1,cmp1);
for(int i=1;i<=m;i++){
p[br[i].id]=i;
}
sort(t+l,t+r+1,cmp);
for(int i=l;i<=r;i++){
if(t[i].op==1)vis[t[i].x]=1;
}
for(int i=l,_=1;i<=r;i++){
if(t[i].op==1)continue;
while(_<=m){
if(br[_].wei<t[i].y)break;
if(!vis[br[_].id]){
merge(br[_].from,br[_].to,0);
}
_++;
}
for(int j=l;j<=r;j++){
if(t[j].op==2)continue;
if(t[j].id>t[i].id)continue;
if(pd[t[j].x])continue;
pd[t[j].x]=1;
if(t[j].y>=t[i].y){
merge(br[p[t[j].x]].from,br[p[t[j].x]].to,1);
}
}
for(int j=l;j<=r;j++){
if(t[j].op==2)continue;
if(pd[t[j].x])continue;
// if(t[j].id<=t[i].id)continue;
if(br[p[t[j].x]].wei>=t[i].y){
// if(br[p[t[j].x]].from==0||br[p[t[j].x]].to==0){
// cerr<<t[j].x<<endl;
// exit(0);
// }
merge(br[p[t[j].x]].from,br[p[t[j].x]].to,1);
}
}
ans[t[i].id]=siz[find(t[i].x)];
while(!st.empty()){
siz[st.top().second]-=siz[st.top().first];
f[st.top().first]=st.top().first;
st.pop();
}
for(int j=l;j<=r;j++){
if(t[j].op==2)continue;
pd[t[j].x]=0;
}
}
for(int i=r;i>=l;i--){
if(t[i].op==1){
br[p[t[i].x]].wei=t[i].y;
vis[p[t[i].x]]=0;
}
}
for(int i=1;i<=n;i++){
f[i]=i;
siz[i]=1;
}
}
int main()
{
// freopen("q.in","r",stdin);
// freopen("q.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&br[i].from,&br[i].to,&br[i].wei);
br[i].id=i;
}
for(int i=1;i<=n;i++){
f[i]=i;
dfn[i]=i;
siz[i]=1;
}
scanf("%d",&q);
T=1500;
// T=sqrt(q);
// T=1;
// T=q;
for(int i=1;i<=q;i++){
scanf("%d%d%d",&t[i].op,&t[i].x,&t[i].y);
o[i]=(t[i].op==2);
t[i].id=i;
}
sum=(q+T-1)/T;
for(int i=1;i<=sum;i++){
lef[i]=rig[i-1]+1;
rig[i]=lef[i]+T-1;
}
rig[sum]=q;
for(int i=1;i<=sum;i++){
solve(lef[i],rig[i],i);
}
for(int i=1;i<=q;i++){
if(o[i])printf("%d\n",ans[i]);
}
}
閒話
感覺這次模擬賽後兩題比較有難度,至少我不會,但賽時確實盡力在想了。前兩題沒掛分,還是有一點優勢的。