字符串一直是蒟蒻的弱项啊
一直不会用map……
恰巧最近刚刚学会替罪羊树这种 “暴力即优美” 的数据结构
于是就想来试一试,结果一遍过,蒟蒻自己都不敢相信
现在为大家献上一个新的方法~
struct node{
int l,r,size,fact,val2;
string val;
bool exist;
}tzy[100005];
//l和r分别表示左右节点
//size和fact是替罪羊树的子树大小和子树真实大小
//val2就是含金量
//val来存单词
//exist表示该节点是否存在
有了结构后,我们就可以来实现替罪羊树了。
和标准替罪羊树没有什么区别
多写一个findval2()
函数就好
int findval2(string val){
int now = root;
while(now){
if(tzy[now].val==val)break;
if(val>tzy[now].val)//直接利用string的比较
now = tzy[now].r;
else
now = tzy[now].l;
}
return tzy[now].val2;
}
完整代码:
#include<bits/stdc++.h>
using namespace std;
const double alpha = 0.75;
struct node{
int l,r,size,fact,val2;
string val;
bool exist;
}tzy[100005];
int tot,root;
void newt(int &now,string val,int val2){
now = ++tot;
tzy[now].val = val;
tzy[now].val2 = val2;
tzy[now].size=tzy[now].fact = 1;
tzy[now].exist = true;
}
bool unb(int now){
if(max(tzy[tzy[now].l].size,tzy[tzy[now].r].size)>tzy[now].size*alpha
|| tzy[now].size-tzy[now].fact>tzy[now].size*0.3)
return true;
return false;
}
vector <int> v;
void bl(int now){
if(!now)return;
bl(tzy[now].l);
if(tzy[now].exist)
v.push_back(now);
bl(tzy[now].r);
}
void lift(int l,int r,int &now){
if(l==r){
now = v[l];
tzy[now].l = tzy[now].r = 0;
tzy[now].size=tzy[now].fact=1;
return;
}
int m = (l+r)>>1;
while(l<m&&tzy[v[m]].val==tzy[v[m-1]].val)
m--;
now = v[m];
if(l<m)lift(l,m-1,tzy[now].l);
else tzy[now].l = 0;
lift(m+1,r,tzy[now].r);
tzy[now].size = tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;
tzy[now].fact = tzy[tzy[now].l].fact+tzy[tzy[now].r].fact+1;
}
void rebuild(int &now){
v.clear();
bl(now);
if(v.empty()){
now = 0;
return ;
}
lift(0,v.size()-1,now);
}
void update(int now,int end){
if(!now)return;
if(tzy[end].val<tzy[now].val)
update(tzy[now].l,end);
else
update(tzy[now].r,end);
tzy[now].size = tzy[tzy[now].l].size+tzy[tzy[now].r].size+1;
}
void check(int &now,int end){
if(now==end)return ;
if(unb(now)){
rebuild(now);
update(root,now);
return;
}
if(tzy[end].val<tzy[now].val)
check(tzy[now].l,end);
else
check(tzy[now].r,end);
}
void insert(int &now,string val,int val2){
if(!now){
newt(now,val,val2);
check(root,now);
return ;
}
tzy[now].size++;
tzy[now].fact++;
if(val<tzy[now].val)
insert(tzy[now].l,val,val2);
else
insert(tzy[now].r,val,val2);
}
void del(int now,string val){
if(tzy[now].exist&&tzy[now].val==val){
tzy[now].exist = false;
tzy[now].fact--;
check(root,now);
return ;
}
tzy[now].fact--;
if(val<tzy[now].val)
del(tzy[now].l,val);
else
del(tzy[now].r,val);
return;
}
int findval2(string val){
int now = root;
while(now){
if(tzy[now].val==val)break;
if(val>tzy[now].val)
now = tzy[now].r;
else
now = tzy[now].l;
}
return tzy[now].val2;
}
signed main(void){
int n,mod,val2,ans = 0;
string p,x;
cin>>n>>mod;
while(n--){
cin>>p>>val2;
insert(root,p,val2);
}
while(getline(cin,x)){
string st;
int len = x.length();
for(int i=0;i<len;++i){
if(x[i]==' '||x[i]==','||x[i]=='.'||x[i]=='!'||x[i]=='?'){
ans+=findval2(st);
ans%=mod;
st="";
}
else st+=x[i];
}
}
cout<<ans;
return 0;
}