专题复习5-字符串
POI2010 Antisymmetry
- 用HASH去维护一下就好了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const int M=514514;
struct Hash
{
ull h[M],base=131,P[M];
void init(char s[M])
{
int n=strlen(s+1);
P[0]=1;
for(int i=1;i<=n;i++) P[i]=P[i-1]*base,h[i]=h[i-1]*base+s[i];
}
ull calc(int l,int r) {return h[r]-h[l-1]*P[r-l+1];}
}h1,h2;
int n;
char s1[M],s2[M];
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d",&n);
scanf("%s",s1+1);
for(int i=1;i<=n;i++) s2[i]='0'+((s1[n-i+1]-'0')^1);
h1.init(s1),h2.init(s2);
ll ans=0;
for(int i=1;i<n;i++)
{
int d=min(i,n-i);
int L=1,R=d,res=0;
while(L<=R)
{
int mid=(L+R)>>1;
if(h1.calc(i-mid+1,i)==h2.calc(n-i-mid+1,n-i)) res=mid,L=mid+1;
else R=mid-1;
}
ans+=res;
}
cout<<ans;
return 0;
}
B. Bovine Genomics
1 |
|
C. friends
- HASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53const int maxn = 2e6+26;
const ull base = 2333;
ull Hash[maxn],Pow[maxn];
char s[maxn];
map<ull,int> vis;
ull cal(int l,int r) {
if(r < l) return 0;
return Hash[r] - Hash[l-1]*Pow[r-l+1];
}
bool s2;
int main() {
int len;
cin >> len;
scanf("%s",s+1);
if(len%2==0||len==1) {
puts("NOT POSSIBLE");
return 0;
}
int k = (len+1)>>1;
Pow[0] = 1;
for(int i = 1; i <= len; ++i) {
Hash[i] = Hash[i-1]*base+(ull)s[i];
Pow[i] = Pow[i-1]*base;
}
int pos = -1;
for(int i = 1; i <= len; ++i) {
ull val1,val2;
if(i < k) {
val2 = cal(k+1,len);
val1 = cal(i+1,k)+cal(1,i-1)*Pow[k-i];
} else if(i == k) {
val1 = cal(1,k-1);
val2 = cal(k+1,len);
} else {
val1 = cal(1,k-1);
val2 = cal(i+1,len)+cal(k,i-1)*Pow[len-i];
}
if(val1 == val2) {
if(pos != -1 && !vis[val1]) {
puts("NOT UNIQUE");
return 0;
} else pos = i,vis[val1] = 1;
}
}
if(pos != -1) {
for(int i = 1; i<=len && k>1; ++i) {
if(i == pos) continue;
putchar(s[i]);
k--;
}
} else puts("NOT POSSIBLE");
return 0;
}
D. 似乎在梦中见过的样子
- KMP 的 高级应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using namespace std;
int p[21000],bak[21000];
char st[21000];
int main()
{
scanf("%s",st+1);int n=strlen(st+1);
int k;
scanf("%d",&k);
int ans=0;
bak[0]=999999999;
for(int t=1;t<=n;t++)
{
p[t]=t-1;bak[t]=999999999;
for(int i=t+1;i<=n;i++)
{
int j=p[i-1];
while(st[j+1]!=st[i]&&j!=(t-1)) j=p[j];
if(st[j+1]==st[i]) j++;
p[i]=j;
bak[i]=bak[j];
if(p[i]-t+1>=k) bak[i]=min(bak[i],p[i]-t+1);
if(bak[i]>=k&&2*bak[i]<=i-t) ans++;
}
}
printf("%d\n",ans);
return 0;
}
E. 关键位置操作
- 直接用线段树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using namespace std;
const int Maxn=2e6+5;
inline int R()
{
char c;int sign=1,res=0;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1;res+=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
return res*sign;
}
int a[Maxn],n,m,sum[Maxn*4],N=1,NN=0,ADD[Maxn*4],size[Maxn*4];
void add(int root,int val)
{
sum[root]+=size[root]*val;
ADD[root]+=val;
}
void pushdown(int root)
{
if(ADD[root])
{
add(ls,ADD[root]);
add(rs,ADD[root]);
ADD[root]=0;
}
}
void build(int root,int deep,int sur)
{
if(deep==NN)
{
sum[root]=a[sur];
size[root]=(sur<=n);
return;
}
build(ls,deep+1,sur);
build(rs,deep+1,sur+(1<<deep));
sum[root]=sum[ls]+sum[rs];
size[root]=size[ls]+size[rs];
}
void modify(int root,int deep,int arr,int sur,int value)
{
if(deep==arr&&sur!=0) return;
pushdown(root);
if(deep==arr) return add(root,value);
if(sur&1) modify(rs,deep+1,arr,sur>>1,value);
else modify(ls,deep+1,arr,sur>>1,value);
sum[root]=sum[ls]+sum[rs];
}
int query(int root,int deep,int arr,int sur)
{
if(deep==arr&&sur!=0) return 0;
pushdown(root);
if(deep==arr) return sum[root];
if(sur&1) return query(rs,deep+1,arr,sur>>1);
else return query(ls,deep+1,arr,sur>>1);
}
signed main()
{
n=R();m=R();
while(N<=n) N<<=1,NN++;
for(int i=1;i<=n;i++) a[i]=R();
build(1,0,1);
int op,p,k,pre=0;
while(m--)
{
op=R();p=R();k=R();
if(op==1)//修改
{
int v=R();
if(k!=0)modify(1,0,min(NN,p),k-1,v);
else modify(1,0,min(NN,p),(1<<(min(NN,p)))-1,v);
}
else if(k!=0)printf("%lld\n",pre=query(1,0,min(NN,p),k-1));
else printf("%lld\n",pre=query(1,0,min(NN,p),(1<<(min(NN,p)))-1));
}
} - 字典树逆推
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using namespace std;
int read() {
int re = 0;
bool sig = false;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-')
sig = true;
c = getchar();
}
while(c >= '0' && c <= '9')
re = (re << 1) + (re << 3) + c - '0',
c = getchar();
return sig ? -re : re;
}
int trie[nn][3] , num[nn];
ll a[nn] , tag[nn] , dat[nn];
int n , m;
void build() {
int top = 1;
for(int i = 1 ; i <= n ; i++) {
int tmp = i;
int p = 1;
while(tmp != 0) {
if(trie[p][tmp & 1] == 0)
trie[p][tmp & 1] = ++top;
p = trie[p][tmp & 1];
tmp >>= 1;
}
a[p] = dat[p] = read();
num[p]++;
}
}
void dfs(int p) {
if(p == 0)return;
dfs(trie[p][0]);
dfs(trie[p][1]);
dat[p] += dat[trie[p][0]] + dat[trie[p][1]];
num[p] += num[trie[p][0]] + num[trie[p][1]];
tag[p] = 0;
}
inline void spread(int p) {//懒标记下传
if(p == 0) {
tag[p] = 0;
return;
}
if(tag[p] != 0) {
tag[trie[p][0]] += tag[p];
dat[trie[p][0]] += num[trie[p][0]] * tag[p];
if(a[trie[p][0]] != -1)
a[trie[p][0]] += tag[p];
tag[trie[p][1]] += tag[p];
dat[trie[p][1]] += num[trie[p][1]] * tag[p];
if(a[trie[p][1]] != -1)
a[trie[p][1]] += tag[p];
}
tag[p] = 0;
}
void change(int x , int y , ll v , int p) {//修改,使用递归的方式,有助于更新dat值
if(x == 0) {
if(a[p] != -1)
a[p] += v;
dat[p] += v * num[p];
tag[p] += v;
return;
}
spread(p);
change(x - 1 , y >> 1 , v , trie[p][y & 1]);
if(y == 0 && a[p] != -1) {
a[p] += v;
}
dat[p] = dat[trie[p][0]] + dat[trie[p][1]];
if(a[p] != -1)
dat[p] += a[p];
}
int query() {//查询
int x = read() , y = read();
ll res = 0;
int p = 1;
y %= (1 << x);
for(int i = 1 ; i <= x ; i++) {
spread(p);
if(y == 0)
res += dat[p] - dat[trie[p][0]] - dat[trie[p][1]];
p = trie[p][y & 1];
y >>= 1;
}
res += dat[p];
printf("%lld\n" , res);
return res;
}
int main() {
memset(a , -1 , sizeof(a));//值为-1代表该结点没有数字
n = read(); m = read();
build();
dfs(1);
ll lastans = 0;
for(int i = 1 ; i <= m ; i++) {
int op;
op = read();
//op = (op + lastans) % 2 + 1;
if(op == 1) {
int x , y , v;
x = read(); y = read(); v = read();
change(x , y % (1 << x) , (ll)v , 1);
}
else
lastans = query();
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ysmmm的快乐小屋!