今天又回来了
寝室还不错。
没有课程所以就随便练题
结果谜之卡常wa掉,一下午简直绝望
明明代码都是一样的
大佬们忙着考试只有下次再问了
但是还是自学了一波回文树
所以今天就不改那道题了,把回文树记下来
反正思路挺简单的,就是代码莫名其妙(感觉我被std骗了)
快乐
回文树
–其实和kmp呀,ac自动机很像,可以说是一摸一样了
重点也是那个fail指针,其实整体难度不大
留下一个很清晰的博客
http://blog.csdn.net/u013368721/article/details/42100363
附加自己打的板子
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=3e5+5;
struct plr_tree{
int next[MAXN][26],fail[MAXN],len[MAXN],sum[MAXN],num[MAXN],s[MAXN];
int last,n,p;
int add(int l){
for(int i=0;i<26;i++) next[p][i]=0;
sum[p]=num[p]=0,len[p]=l;
return p++;
}
void init(){
p=n=last=0,s[n]=-1,fail[0]=1;
add(0),add(-1);
}
int get_fail(int x){
while(s[n-len[x]-1]!=s[n]) x=fail[x];
return x;
}
void extend(int c){
s[++n]=c;
int cur=get_fail(last);
if(!next[cur][c]){
int now=add(len[cur]+2);
fail[now]=next[get_fail(fail[cur])][c];
next[cur][c]=now,num[now]=num[fail[now]]+1;
}
last=next[cur][c],sum[last]++;
}
void count(){
for(int i=p-1;i>=0;i--) sum[fail[i]]+=sum[i];
}
}pt;
char s[MAXN];
int l;
long long ans;
int main(){
scanf("%s",s);
l=strlen(s),pt.init();
for(int i=0;i<l;i++) pt.extend(s[i]-'a');
pt.count();
for(int i=0;i<pt.p;i++) ans=max(ans,1ll*pt.sum[i]*pt.len[i]);
cout<<ans;
return 0;
}
jzoj 4754 矩阵
http://172.16.0.132/senior/#contest/show/2657/1
–真的要把人气死。
显然,因为权值非负,一个矩阵的权值肯定不比其子矩阵小。那么建立一个堆,开始把
所有最小的和谐矩阵加入堆,每次从堆中取出最小的和谐矩阵,同时扩展出最多2个新的和
谐矩阵(左右二选一,上下二选一),注意判重,重复 k 次即可。
时间复杂度 O(NM+klog(n^2+2k))。
问题就在这个判重,hash,map,set能打的都打了,还是玄学错误
留下两个代码(一个超时,一个wa)
呵呵
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
const int MAXN=1e3+5;
int n,m,mina,minb,k;
long long ma[MAXN][MAXN];
struct matrix{
long long sum;
int x,y,a,b;
matrix(){x=y=a=b=sum=0;}
matrix(int x,int y,int a,int b,long long sum):x(x),y(y),a(a),b(b),sum(sum){}
bool operator <(matrix t)const{
return sum>t.sum;
}
};
priority_queue<matrix>q;
typedef pair<int,int>p1;
typedef pair<p1,p1>p2;
map<p2,bool> hash;
long long calc(int x,int y,int a,int b){
return ma[a][b]-ma[a][y-1]-ma[x-1][b]+ma[x-1][y-1];
}
int main(){
cin>>n>>m>>mina>>minb>>k;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
scanf("%lld",&ma[i][j]);
ma[i][j]+=ma[i-1][j]+ma[i][j-1]-ma[i-1][j-1];
}
for(int i=1;i<=n-mina+1;i++) for(int j=1;j<=m-minb+1;j++){
int a=i+mina-1,b=j+minb-1;
q.push(matrix(i,j,a,b,calc(i,j,a,b)));
}
k--;
while(k--){
matrix t=q.top();q.pop();
p2 p=make_pair(make_pair(t.x,t.y),make_pair(t.a,t.b));
while(hash[p]) t=q.top(),q.pop(),p=make_pair(make_pair(t.x,t.y),make_pair(t.a,t.b));
hash[p]=1;
if(t.a<n) q.push(matrix(t.x,t.y,t.a+1,t.b,calc(t.x,t.y,t.a+1,t.b)));
if(t.b<m) q.push(matrix(t.x,t.y,t.a,t.b+1,calc(t.x,t.y,t.a,t.b+1)));
}
cout<<q.top().sum;
return 0;
}
第二个
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
const int MAXN=1e3+5;
int n,m,mina,minb,k;
long long ma[MAXN][MAXN];
struct matrix{
long long sum;
int x,y,a,b;
matrix(){x=y=a=b=sum=0;}
matrix(int x,int y,int a,int b,long long sum):x(x),y(y),a(a),b(b),sum(sum){}
bool operator <(matrix t)const{
return sum>t.sum;
}
};
priority_queue<matrix>q;
typedef pair<int,int>p1;
typedef pair<p1,p1>p2;
map<p2,bool> hash;
long long calc(int x,int y,int a,int b){
return ma[a][b]-ma[a][y-1]-ma[x-1][b]+ma[x-1][y-1];
}
p2 mp(int x,int y,int a,int b){
return make_pair(make_pair(x,y),make_pair(a,b));
}
bool isu(p2 t){
if(hash[t]) return 1;
hash[t]=1;
}
int main(){
cin>>n>>m>>mina>>minb>>k;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
scanf("%lld",&ma[i][j]);
ma[i][j]+=ma[i-1][j]+ma[i][j-1]-ma[i-1][j-1];
}
for(int i=1;i<=n-mina+1;i++) for(int j=1;j<=m-minb+1;j++){
int a=i+mina-1,b=j+minb-1;
q.push(matrix(i,j,a,b,calc(i,j,a,b)));
hash[mp(i,j,a,b)]=1;
}
k--;
while(k--){
matrix t=q.top();q.pop();
if(t.a<n&&!isu(make_pair(make_pair(t.x,t.y),make_pair(t.a+1,t.b)))) q.push(matrix(t.x,t.y,t.a+1,t.b,calc(t.x,t.y,t.a+1,t.b)));
if(t.b<m&&!isu(make_pair(make_pair(t.x,t.y),make_pair(t.a,t.b+1)))) q.push(matrix(t.x,t.y,t.a,t.b+1,calc(t.x,t.y,t.a,t.b+1)));
}
cout<<q.top().sum;
return 0;
}
jzoj 4744 同余
http://172.16.0.132/senior/#main/show/4744
竟然是做过的
快乐
观察到,其实要求的是某⼀范围内 kp + q 的个数,当 p 较⼤时,k 的取值范围很⼩。不妨
设“较⼤”的界限是 > K。
考虑将问题拆开来并排序,这样每个问题就变成了询问 1 ∼ r 中有多少个 kp + q。维护⼀
个哈希数组,h[i] 表示 i 有多少个;以及⼀个模数数组 g[i][j],表示模 i 为 j 有多少个。
每次指针向右移,直到移动到当前询问的位置,每移⼀次就将这个数分别在两个数组内标
记,复杂度总体是 O (nK)。
每次询问时,对于较⼩的 p 直接在 g 中查询,对于较⼤的 p 枚举 k 并在 h 中查询,复杂度
是 O(m*ai/K)。
可以看出 K =√ai = 100 时最优。
lower_bound大法好
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=1e5+5;
int n,m;
int a[MAXN];
vector<int>v_a[10005],v_b[105][105];
int l,r,p,v;
int ans;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
v_a[a[i]].push_back(i);
}
for(int i=1;i<=100;i++)
for(int j=1;j<=n;j++)
v_b[i][a[j]%i].push_back(j);
int k=0;
while(m--){
scanf("%d%d%d%d",&l,&r,&p,&v);
int L,R;
if(p<=100){
if(!v_b[p][v].size()){
printf("0\n");
continue;
}
L=lower_bound(v_b[p][v].begin(),v_b[p][v].end(),l)-v_b[p][v].begin();
R=lower_bound(v_b[p][v].begin(),v_b[p][v].end(),r)-v_b[p][v].begin();
if((!R&&v_b[p][v][R]>r)||L>=v_b[p][v].size()){
printf("0\n");
continue;
}
while(R>=v_b[p][v].size()||r<v_b[p][v][R])
R--;
printf("%d\n",R-L+1);
}
else{
ans=0;
for(v;v<=10000;v+=p){
if(!v_a[v].size())
continue;
L=lower_bound(v_a[v].begin(),v_a[v].end(),l)-v_a[v].begin();
R=lower_bound(v_a[v].begin(),v_a[v].end(),r)-v_a[v].begin();
if((!R&&v_a[v][R]>r)||L>=v_a[v].size())
continue;
while(R>=v_a[v].size()||r<v_a[v][R])
R--;
ans+=R-L+1;
}
printf("%d\n",ans);
}
}
return 0;
}
剩下的时间在看省选的题
结果最后都是转去百度补学各种模板。
QAQ
还没打完,但有在学