洛谷 P3501 [POI2010]ANT-Antisymmetry 题解
每日一题 day72 打卡
Analysis
这道题一开始我就想到了暴力哈希的做法,但是因为n有 500000 那么大,所以单纯的哈希肯定是不行的。
于是我就上网翻了几篇题解,发现都是二分+哈希,于是思考二分的做法。
之前我就有一个想法,找到所有相邻不一样的点(即本身是反对称的且可能是更大的反对称串的对称轴),再判断其能延伸为多少个反对称串。(时间显然超限)
现在只需二分延伸串的长度的一半(即 l )来实现就好了。
以下为代码实现:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ull unsigned long long 6 #define int long long 7 #define maxn 500010 8 #define rep(i,s,e) for(register int i=s;i<=e;++i) 9 #define dwn(i,s,e) for(register int i=s;i>=e;--i) 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1; 14 char c=getchar(); 15 while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} 16 while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();} 17 return f*x; 18 } 19 inline void write(int x) 20 { 21 if(x<0){putchar('-');x=-x;} 22 if(x>9)write(x/10); 23 putchar(x%10+'0'); 24 } 25 int n,base=13131,ans; 26 char str[maxn],counter_str[maxn]; 27 ull power[maxn]; 28 struct node 29 { 30 ull x,y; 31 }hash[maxn]; 32 void init() 33 { 34 power[0]=1; 35 rep(i,1,n) power[i]=power[i-1]*base; 36 rep(i,1,n) hash[i].x=hash[i-1].x*base+str[i]-'0'; 37 dwn(i,n,1) hash[i].y=hash[i+1].y*base+counter_str[i]-'0'; 38 } 39 inline void dich(int x) 40 { 41 int l=0,r=min(x,n-x); 42 while(l<r) 43 { 44 int mid=(l+r+1)>>1; 45 if(hash[x].x-hash[x-mid].x*power[mid]==hash[x+1].y-hash[x+1+mid].y*power[mid]) l=mid; 46 else r=mid-1; 47 } 48 ans+=l; 49 } 50 signed main() 51 { 52 n=read(); 53 scanf("%s",str+1); 54 rep(i,1,n) 55 { 56 if(str[i]=='0') counter_str[i]='1'; 57 else counter_str[i]='0'; 58 } 59 init(); 60 rep(i,1,n) 61 if(str[i]!=str[i+1]) 62 dich(i); 63 write(ans); 64 return 0; 65 }
如有失误请各位大佬斧正(反正我不认识斧正是什么意思)