整天挨着毛爷爷,压力好大。。

看毛爷爷即将炖完NOI,我的确也该刷了

原则是从头到尾自己想(虽然看了一次题解),可以不A掉。

NOI2009

day1:

T1

题目略神,我还是不讲了。。。(就这题我WA了好多遍 TAT)

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <vector> #define N 20010 using namespace std; struct edge{
int x,to;
}E[N<<]; int n,a[N],pre[N],totE,g[N];
bitset<N> v;
vector<int> G[N]; #define p G[x][i] void ade(int x,int y){
G[x].push_back(y);
} int find(int x){
v[x]=;
int len=G[x].size();
for(int i=;i<len;i++)
if(!v[p]){
v[p]=;
if(!pre[p]||find(pre[p])){
pre[p]=x; pre[x]=p;
return ;
}
}
return ;
} int main(){
freopen("transform.in","r",stdin);
freopen("transform.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=;i<=n;i++){
if(i-a[i]>=) G[i].push_back(n+i-a[i]);
else G[i].push_back(n+i-a[i]+n);
if(i+a[i]<=n) G[i].push_back(n+i+a[i]);
else G[i].push_back(i+a[i]);
}
for(int i=;i<=n;i++) sort(G[i].begin(),G[i].end());
int ans=;
for(int i=n;i>=;i--){
v.reset();
if(find(i)) ans++;
}
if(ans!=n){
puts("No Answer");
}
else{
for(int i=;i<n;i++) printf("%d ",pre[i]-n-);
printf("%d\n",pre[n]-n-);
}
return ;
}

T2

脑补一下,这个应该是一个单峰函数,果断三分。

爆long long QAQ,这要是NOI我就被坑死啦,long double过。

 #include <cstdio>
#include <cstring>
#include <algorithm> #define LL long long
#define N 200010
#define LD long double using namespace std; int n,P;
int len[N],pre[N];
LL L;
LD f[N];
char S[N][]; LD qpow(LD x,LL n){
LD ans=;
for(;n;n>>=,x*=x)
if(n&) ans*=x;
return ans;
} LD Abs(LL x){
if(x<) return -(LD)x;
return (LD)x;
} LD F(int i,int j){
return f[j]+
qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P);
} int find(int i){
int l=,r=i-,m1,m2;
while(r-l>){
m1=l+(r-l)/;
m2=r-(r-l)/;
if(F(i,m1)<F(i,m2)) r=m2;
else l=m1;
}
LD ans=F(i,);
int pos=;
for(int t=l;t<=r;t++)
if(F(i,t)<ans){
ans=F(i,t);
pos=t;
}
return pos;
} void print(int t){
if(pre[t]) print(pre[t]);
for(int i=pre[t]+;i<t;i++){
printf("%s ",S[i]);
}
printf("%s\n",S[t]);
} int main(){
freopen("noi09_poet.in","r",stdin);
freopen("noi09_poet.out","w",stdout);
int T;
scanf("%d",&T);
while(T--){
scanf("%d %lld %d",&n,&L,&P);
for(int i=;i<=n;i++){
scanf("%s",S[i]);
len[i]=strlen(S[i]);
}
for(int i=;i<=n;i++) len[i]+=len[i-];
memset(f,,sizeof(f));
f[]=;
for(int i=;i<=n;i++){
int j=find(i);
f[i]=f[j]+qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P);
pre[i]=j;
}
if(f[n]>1e18){
puts("Too hard to arrange");
}
else{
printf("%lld\n",(LL)(f[n]));
print(n);
}
puts("--------------------");
}
return ;
}

T3

QAQ好难,膜毛爷爷。

首先所谓 (频度 x 深度) 我们可以每过一层就加上当前的频度得到答案。

利用先序遍历的特殊性质(TAT 其实想到这个就差不多了),考虑dp。

f[i][j][k] 表示先序遍历从 i 到 j 作为一个子树(可能多个),而且满足所有权值小于等于k的最小花费。

转移分两种情况,修改当前root权值,修改子树权值。

$O(n^4)$ dp即可。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> #define N 80
#define LL long long
#define INF 0x7f7f7f7f7f7f7f7fLL
#define debug(x) cout<<#x<<" = "<<x<<endl; using namespace std; int n,tot0;
int a[N],b[N],c[N],X[N];
LL K;
LL dp[N][N][N];
LL s[N][N]; /*
O(n^5) f[i][j][k]
i到j之间的所有数值大于k,
消灭当前点 f[i][j][k] = min{ f[i][p-1][k] + f[p+1][j][k] + s[i][j] + K }
不消灭当前点 f[i][j][k] = min{ f[i][p-1][b[p]] + f[p+1][j][b[p]] + s[i][j] }
*/ LL F(int i,int j,int k){
if(i>j) return ;
// printf("%d %d %d\n",i,j,k);
if(dp[i][j][k]) return dp[i][j][k];
if(i==j) return dp[i][j][k]=b[i]<k ?K+c[i]:c[i];
dp[i][j][k]=INF;
for(int p=i;p<=j;p++){ //改当前点权
dp[i][j][k]=min(dp[i][j][k],F(i,p-,k) + F(p+,j,k) + s[i][j] + K);
if(b[p]>=k){ //不改当前点权
dp[i][j][k]=min(dp[i][j][k],F(i,p-,b[p]) + F(p+,j,b[p]) + s[i][j]);
}
}
return dp[i][j][k];
} void init(){
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)
if(a[i]>a[j]){
swap(a[i],a[j]);
swap(b[i],b[j]);
swap(c[i],c[j]);
}
sort(X+,X+n+);
tot0=;
for(int i=;i<=n;i++)
if(X[i]!=X[i-]) X[++tot0]=X[i];
for(int i=;i<=n;i++)
b[i]=lower_bound(X+,X+tot0+,b[i])-X;
for(int i=;i<=n;i++){
s[i][i]=c[i];
for(int j=i+;j<=n;j++)
s[i][j]=s[i][j-]+c[j];
}
} int main(){
freopen("treapmod.in","r",stdin);
freopen("treapmod.out","w",stdout);
scanf("%d%d",&n,&K);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++){
scanf("%d",&b[i]);
X[i]=b[i];
}
for(int i=;i<=n;i++) scanf("%d",&c[i]);
init();
LL ans=INF;
for(int i=;i<=n;i++){
ans=min(ans,F(,n,b[i]));
}
cout<<ans<<endl;
return ;
}

day2

T1:

裸网络流,注意要拓扑一下,还要判环,环内的植物不能碰。

T2:

又是一道$dp$,思路很神(TAT 实在不会,看了题解)。

就是将 平方和 转化为结果相同的方案对数(自己也算)

然后裸dp上。

 #include <cstdio>
#include <cstring>
#include <algorithm> #define N 510
#define mod 1024523 using namespace std; /*
f[i][j][k]表示上面取了上i下j,上k。
*/ char S1[N],S2[N];
int f[N][N][N],n,m; int add(int a,int b){
if(a+b<mod) return a+b;
return a+b-mod;
} int main(){
freopen("ballb.in","r",stdin);
freopen("ballb.out","w",stdout);
scanf("%d%d%s%s",&n,&m,S1,S2);
reverse(S1,S1+n);
reverse(S2,S2+m);
f[][][]=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
for(int k=;k<=n;k++){
if(!f[i][j][k]) continue;
int l = i+j-k;
if(l<) break;
//printf("f[%d][%d][%d] = %d\n",i,j,k,f[i][j][k]);
if(i<n && k<n && S1[i]==S1[k]){
f[i+][j][k+] = add(f[i+][j][k+],f[i][j][k]);
}
if(i<n && l<m && S1[i]==S2[l]){
f[i+][j][k] = add(f[i+][j][k],f[i][j][k]);
}
if(j<m && k<n && S2[j]==S1[k]){
f[i][j+][k+] = add(f[i][j+][k+],f[i][j][k]);
}
if(j<m && l<m && S2[j]==S2[l]){
f[i][j+][k] = add(f[i][j+][k],f[i][j][k]);
}
}
}
}
printf("%d\n",f[n][m][n]);
return ;
}

T3:

很好的提交答案题。

做好了70分吧。

NOI 2008

TAT QAQ QWQ TWT

题出这么难也是醉了。

day1:

T1

找环然后分类讨论,情况不多就三种。

可是好多细节呀,蒟蒻我是调不出来的。

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; template<typename T> T abs(T x){
if(x>) return x;
return -x;
}
template<typename T> T gcd(T x, T y){
for(T t;x!=;t=x,x=y%x,y=t);
return y;
} const int Maxn =;
const int Maxm =; struct edge{
int to,x,v;
}Edges[Maxm]; int totE=,head[Maxn]; void addedge(int u,int v,int w){
Edges[++totE]=(edge){head[u],v,w};
head[u]=totE;
} int n,m,ans=,d[Maxn],maxt,mint;
bool vis[Maxn]; void dfs(int x){
vis[x]=;
for(int i=head[x];i;i=Edges[i].to){
int p=Edges[i].x;
if(vis[p]) ans=gcd(ans,abs(d[x]+Edges[i].v-d[p]));
else d[p]=d[x]+Edges[i].v,dfs(p);
}
} void find(int x){
vis[x]=;
maxt=max(maxt,d[x]);
mint=min(mint,d[x]);
for(int i=head[x];i;i=Edges[i].to){
int p=Edges[i].x;
if(!vis[p]) d[p]=d[x]+Edges[i].v,find(p);
}
} int main(){
freopen("party2008.in","r",stdin);
freopen("party2008.out","w",stdout);
scanf("%d%d",&n,&m);
int u,v,tmp;
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
addedge(u,v,);
addedge(v,u,-);
}
for(int i=;i<=n;i++)
if(!vis[i]) d[i]=,dfs(i);
if(ans){
for(tmp=;tmp<ans&&ans%tmp;tmp++);
//cout<<"case 1\n";
}
else{
memset(vis,,sizeof(vis));
tmp=;
for(int i=;i<=n;i++)
if(!vis[i]){
maxt=mint=d[i]=;
find(i);
ans+=maxt-mint+;
}
}
if(ans<) ans=tmp=-;
printf("%d %d\n",ans,tmp);
return ;
}

T2

相对温暖的一道题。

可以发现一个条件:答案是 $O(logn)$ 级的(为啥我也不知道)。

然后变成了经典问题,直接枚举【不便利值】树形dp方案数,$f[i][j]$表示 $i$ 这个点向下连 $j$ 条边的方案数,直到方案数不为0为止。

注意0和mod后为0不同,因为要判断是否有方案,所以如果是因为mod而变成的0记做mod。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue> #define Maxn 100010
typedef long long LL; using namespace std; int n,m,Q,dep[Maxn];
LL f[Maxn][][];
vector<int> G[Maxn]; /*
link = f[p][j][0] + f[p][j][1]
not_link = f[p][j-1][0] + f[p][j-1][1] + f[p][j-1][2] f[i][j][2] = f[i][j][2] * not_link + f[i][j][2]
f[i][j][1] = f[i][j][1] * not_link + f[i][j][0] * link
f[i][j][0] = f[i][j][0] * not_link
*/ bool find_circle(int x,int tp){
for(int i=;i<G[x].size();i++){
if(G[x][i]==tp) continue;
if(dep[G[x][i]]) return ;
dep[G[x][i]]=dep[x]+;
if(find_circle(G[x][i],x)) return ;
}
return ;
} bool not_a_tree(int x){
dep[x]=;
if(find_circle(x,)) return ;
for(int i=;i<=n;i++)
if(!dep[i]) return ;
return ;
} LL Mod(LL x){
if(x==) return ;
if(x%Q==) return Q;
return x%Q;
} LL dp(int x,int tp,int j){
f[x][j][]=f[x][j][]=0LL;
f[x][j][]=1LL;
for(int i=;i<G[x].size();i++){
int p=G[x][i];
if(p==tp) continue;
dp(p,x,j);
int not_link=,link=;
link =Mod(f[p][j][]+f[p][j][]);
if(j>) not_link =Mod(f[p][j-][]+Mod(f[p][j-][]+f[p][j-][]));
f[x][j][] =Mod(f[x][j][]*not_link)+Mod(f[x][j][]*link);
f[x][j][] =Mod(f[x][j][]);
f[x][j][] =Mod(f[x][j][]*not_link)+Mod(f[x][j][]*link);
f[x][j][] =Mod(f[x][j][]);
f[x][j][] =Mod(f[x][j][]*not_link);
}
return Mod(f[x][j][]+Mod(f[x][j][]+f[x][j][]));
} int main(){
freopen("design.in","r",stdin);
freopen("design.out","w",stdout);
scanf("%d%d%d",&n,&m,&Q);
int u,v,tmp=;
LL ans=;
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
if(n!=m+||not_a_tree()){
puts("-1\n-1");
return ;
}
while(ans<=) ans=dp(,,tmp++);
printf("%d\n%lld\n",tmp-,ans==Q? :ans);
return ;
}

T3

蒟蒻表示自己图论超级渣。

以前看题解过了,现在还不懂。

day2

T1

妈呀,基环外向树上dp,醉了,还是概率dp。

用贪心水到了40分,好像有人说可以70分,咦是我交的题库上的数据太强了吗。

T2

day2的温暖题。

QAQ 但是好寒冷。

直接转化一下,二维树状数组。

 #include <iostream>
#include <cstdio>
#include <cstring> #define Maxn 1010
#define Maxc 1000010 typedef int Se[Maxn*][Maxn<<]; using namespace std; int n,T,len,m;
Se a,b;
struct Cloud{
int t,p;
}clou[Maxc]; void Add(Se a,int x,int y,int d){
for(int i=x+;i<len*+;i+=i&-i)
for(int j=y+;j<(len<<)+;j+=j&-j)
a[i][j]+=d;
} int Ask(Se a,int x,int y){
int ans=;
for(int i=x+;i;i-=i&-i)
for(int j=y+;j;j-=j&-j)
ans+=a[i][j];
return ans;
} void Add1(int x,int y,int d){
Add(a,x,x+y,d);
} void Add2(int x,int y,int d){
Add(b,x-len,y-x+m,d);
} void update(int c,int d){
int t=clou[c].t,p=clou[c].p;
Add1(t,p,d);
if(t<=len) Add1(t+n,p,d);
Add2(t+n,p,d);
if(t>=len) Add2(t,p,d);
} int Ask1(int x0,int y0,int x1,int y1){
return Ask(a,x1,x1+y1) - Ask(a,x0-,x1+y1)
- Ask(a,x1,x0+y0-) + Ask(a,x0-,x0+y0-);
} int Ask2(int x0,int y0,int x1,int y1){
return Ask(b,x1-len,y1-x1+m) - Ask(b,x0-len-,y1-x1+m)
- Ask(b,x1-len,y0-x0+m-) + Ask(b,x0-len-,y0-x0+m-);
} int query(int t,int L,int R){
int ans=Ask1(t,L,t+R,len),d=len==R;
if(!R) return ans;
return ans+=Ask2(t+n-R+d,L-R+d,t+n-,len+R-);
} int main(){
freopen("noi2008_candy.in","r",stdin);
freopen("noi2008_candy.out","w",stdout);
scanf("%d%d",&T,&len);
n=*len; m=*n;
for(int i=;i<=T;i++){
int K,t,c,L,R,d;
scanf("%d%d",&K,&t);
t%=n;
if(K==){
scanf("%d%d%d%d",&c,&L,&R,&d);
clou[c].t=(t-d*L+n)%n;
clou[c].p=R-L;
update(c,);
}
else if(K==){
scanf("%d%d",&L,&R);
printf("%d\n",query(t,L,R));
}
else{
scanf("%d",&c);
update(c,-);
}
}
return ;
}

T3

提交答案题,还没做

继续

NOI2010

Day1

T1:能量采集:SB题,随便搞

 #include <cstdio>
#include <cstring>
#include <algorithm> #define LL long long
#define Maxn 100010 using namespace std; LL n,m,ans;
LL phi[Maxn]={,,}; int main(){
freopen("energy2010.in","r",stdin);
freopen("energy2010.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(n<m) swap(n,m);
for(int i=;i<=m;i++){
if(phi[i]) continue;
for(int j=i;j<=m;j+=i){
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]*(i-)/i;
}
}
for(int i=;i<=m;i++){
ans+=(n/i)*(m/i)*phi[i];
}
ans=(ans-m*n)*+m*n;
printf("%lld\n",ans);
return ;
}

T2:超级钢琴。

区间裂解,就是找到前K大的子区间和

ST+堆,随便搞。

#include <cstdio>
#include <queue>
using namespace std; typedef long long LL; const int maxn = ; struct Node {
LL x; int l, r, i;
bool operator < (const Node &A) const {
return x < A.x;
}
};
priority_queue<Node> pq; int n, K, L, R;
LL S[maxn];
int rmq[][maxn]; void RMQ_init() {
int k = ; for (; ( << k+) < n+; ++ k);
for (int i = ; i <= n; ++ i) rmq[][i] = i; for (int j = ; j <= k; ++ j)
for (int i = ; i+(<<j)- <= n; ++ i) {
int p = rmq[j-][i], q = rmq[j-][i+(<<j-)];
rmq[j][i] = S[p] < S[q] ? p : q;
}
}
int RMQ(int l, int r) {
int z = r-l+;
int k = ; for (; ( << k+) < z; ++ k);
int p = rmq[k][l], q = rmq[k][r-(<<k)+];
return S[p] < S[q] ? p : q;
} int main() {
freopen("piano.in", "r", stdin);
freopen("piano.out", "w", stdout); scanf("%d%d%d%d", &n, &K, &L, &R); for (int i = ; i <= n; ++ i) {
int x; scanf("%d", &x);
S[i] = S[i-] + x;
}
RMQ_init(); for (int i = ; i <= n; ++ i) {
int a = i-R, b = i-L; if (a < ) a = ;
if (b >= ) pq.push((Node){S[i] - S[RMQ(a, b)], a, b, i});
} LL res = ;
while (K --) {
if (pq.empty()) break;
Node x = pq.top(); pq.pop();
res += x.x; int t = RMQ(x.l, x.r);
if (x.l <= t-) pq.push((Node){S[x.i] - S[RMQ(x.l, t-)], x.l, t-, x.i});
if (t+ <= x.r) pq.push((Node){S[x.i] - S[RMQ(t+, x.r)], t+, x.r, x.i});
}
printf("%lld\n", res); fclose(stdin); fclose(stdout);
return ;
}

T3:海拔

不想写对偶图,懒癌犯了,dinic 80何必呢。

Day2

T1:航空管制

很神,但是是贪心。拓扑一下然后直接贪心。

在不看题解下拿了80(二分答案+乱搞)

T2:旅行路线

很懒,裸插头dp,不想捉。

NOI2011

Day1

T1:兔农

很久以前过的了,忘了。

T2:智能车比赛

很SB的水题,最短路,建图叉积一下,貌似我写麻烦了。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib> #define LL long long
#define sqr(x) ((x)*(x))
#define N 8010
#define p E[i].x using namespace std; struct edge{
int x,to;
long double v;
}E[]; struct node{
int x,y,id; void print(){
printf("(%d,%d)",x,y);
} void scan(){
scanf("%d%d",&x,&y);
}
}S,T,P[]; int tot;
queue<int> q; struct road{
node Lu,Ld,Ru,Rd; void scan(){
Ld.scan();
Ru.scan();
Lu=(node){Ld.x,Ru.y};
Rd=(node){Ru.x,Ld.y};
Ld.id=++tot; P[tot]=Ld;
Lu.id=++tot; P[tot]=Lu;
Rd.id=++tot; P[tot]=Rd;
Ru.id=++tot; P[tot]=Ru;
}
}L[N]; int n,totE;
int g[N];
double V;
long double dis[N];
bool v[N]; double dist(node a,node b){
return sqrt(sqr((LL)(a.x-b.x))+sqr((LL)(a.y-b.y)));
} LL cross(node a,node b,node c){
return (c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);
} bool cut(node a,node b,node c,node d){
if(cross(a,c,b)*(LL)cross(a,d,b)>=) return ;
if(cross(c,a,d)*(LL)cross(c,b,d)>=) return ;
return ;
} bool check(node a,node b){
for(int i=;i<=n;i++){
if(cut(a,b,L[i].Ld,L[i].Lu)) return ;
if(cut(a,b,L[i].Lu,L[i].Ru)) return ;
if(cut(a,b,L[i].Rd,L[i].Ru)) return ;
if(cut(a,b,L[i].Ld,L[i].Rd)) return ;
}
return ;
} void addedge(node a,node b){
int x=a.id,y=b.id;
long double d=dist(a,b);
E[++totE]=(edge){y,g[x],d}; g[x]=totE;
E[++totE]=(edge){x,g[y],d}; g[y]=totE;
} void buildgraph(node now){
node up=(node){now.x,now.y+},down=(node){now.x,now.y-};
for(int j=;j<=tot;j++){
if(cross(now,P[j],up)<= && cross(now,P[j],down)>=);
if((j&)== && cross(now,P[j],up)<) up=P[j];
if((j&) && cross(now,P[j],down)>) down=P[j];
if((j&)== && P[j].x>=T.x){
if(cross(now,T,up)<= && cross(now,T,down)>=){
printf("%.10lf\n",dist(S,T)/V);
exit();
}
}
}
} void buildgraph2(node now){
node up=(node){now.x,now.y+},down=(node){now.x,now.y-};
for(int j=tot;j>=;j--){
if(cross(now,P[j],up)>= && cross(now,P[j],down)<=)
addedge(now,P[j]);
if((j&)== && cross(now,P[j],up)>) up=P[j];
if((j&) && cross(now,P[j],down)<) down=P[j];
}
} int main(){
// freopen("car2.in","r",stdin);
freopen("noi2011_car.in","r",stdin);
freopen("noi2011_car.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++) L[i].scan();
S.scan(); S.id=tot+;
T.scan(); T.id=tot+;
if(S.x>T.x) swap(S,T);
scanf("%lf",&V);
for(int i=;i<=tot;i++){
node up=(node){P[i].x,P[i].y+},down=(node){P[i].x,P[i].y-};
for(int j=i+;j<=tot;j++){
if(cross(P[i],P[j],up)<= && cross(P[i],P[j],down)>=)
addedge(P[i],P[j]);
if((j&)== && cross(P[i],P[j],up)<=) up=P[j];
if((j&) && cross(P[i],P[j],down)>=) down=P[j];
}
}
int st=,ed=;
for(int i=;i<=tot;i++){
if(P[i].x==S.x&&P[i].y==S.y) st=i;
if(P[i].x==T.x&&P[i].y==T.y) ed=i;
}
buildgraph(S);
for(int i=;i<=tot+;i++) dis[i]=1e50;
q.push(st); dis[st]=;
while(!q.empty()){
int x=q.front(); q.pop();
v[x]=;
for(int i=g[x];i;i=E[i].to)
if(dis[p]>dis[x]+E[i].v){
dis[p]=dis[x]+E[i].v;
if(!v[p]) q.push(p),v[p]=;
}
}
printf("%.10lf\n",(double)(dis[ed]/V));
return ;
}

T3:阿狸的打字机

树链剖分维护fail树,不错的经典题

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector> #define N 100010
#define MP(x,y) make_pair(x,y)
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define fir first
#define sec second using namespace std; void file(){
freopen("noi2011_type.in","r",stdin);
freopen("noi2011_type.out","w",stdout);
} struct node{
node *ch[],*fail,*fa,*next[];
int v,id;
}*root,*pre[N]; int n,tot,sumv[N],L[N],R[N],g[N],totE,cnt,tott,ansv[N];
char S[N];
vector<pair<int,int> > ask[N]; struct edge{
int x,to;
}E[N<<]; queue<node*> q; void ade(int x,int y){
E[++totE]=(edge){y,g[x]}; g[x]=totE;
} int qsum(int x){
int ans=;
for(;x>;x-=(x&-x)) ans+=sumv[x];
return ans;
} void add(int x,int v){
for(;x<=tot;x+=(x&-x)) sumv[x]+=v;
} void getfail(){
q.push(root);
while(!q.empty()){
node* tmp=q.front(); q.pop();
tmp->id=++tot;
if(tmp!=root) ade(tmp->fail->id,tmp->id);
for(int t=;t<;t++){
if(tmp->ch[t]!=NULL){
if(tmp==root) tmp->ch[t]->fail=root;
else tmp->ch[t]->fail=tmp->fail->ch[t];
q.push(tmp->ch[t]);
}
else{
if(tmp==root) tmp->ch[t]=root;
else tmp->ch[t]=tmp->fail->ch[t];
}
}
}
} #define p E[i].x void dfs(int x){
L[x]=++tott;
for(int i=g[x];i;i=E[i].to) dfs(p);
R[x]=tott;
} void solve(node* x){
add(L[x->id],);
for(int i=ask[x->id].size()-;~i;i--){
int t=ask[x->id][i].fir;
ansv[ask[x->id][i].sec]=qsum(R[t])-qsum(L[t]-);
}
for(int t=;t<;t++)
if(x->next[t]!=NULL) solve(x->next[t]);
add(L[x->id],-);
} int main(){
file();
scanf("%s",S);
root=new node();
node* tmp=root;
for(int i=,len=strlen(S);i<len;i++){
if(S[i]=='P') pre[++cnt]=tmp;
else if(S[i]=='B') tmp=tmp->fa;
else{
int t=S[i]-'a';
if(tmp->ch[t]==NULL){
tmp->ch[t]=new node();
tmp->next[t]=tmp->ch[t];
}
tmp->ch[t]->fa=tmp;
tmp=tmp->ch[t];
}
}
getfail();
dfs(root->id);
scanf("%d",&n);
for(int i=,x,y;i<=n;i++){
scanf("%d%d",&x,&y);
ask[pre[y]->id].push_back(MP(pre[x]->id,i));
}
solve(root);
for(int i=;i<=n;i++)
printf("%d\n",ansv[i]);
fclose(stdin);
fclose(stdout);
return ;
}

Day2

T1:道路修建

233这题。。。。

T2:NOI 嘉年华

读不懂

T3:兔子和蛋蛋

没看

是时候开刷NOI了的更多相关文章

  1. 开刷LeetCode

    还是觉得自己在算法这块太弱鸡了 不多废话开刷吧,LeetCode与算法导论相辅相成双管齐下,期望能填上算法这个坑 解法没意外都是用Python2.7 由于LeetCode有提供Top Solution ...

  2. NOI 动态规划题集

    noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...

  3. 今天想把iphone4刷成ios7.3beta,折腾半天,成功

    今天想把iphone4刷成ios7.3beta,折腾半天,成功 总结如下 1 确认你是无锁机,要是有锁的,就先算了吧.我手里的是台版的无锁,这关过了. 2 得是干净非越狱的,一开始是4.2.1版本的越 ...

  4. leetcode算法刷题(四)——动态规划(二)

    又到了晚上,动态规划,开刷! 第121题 Best Time to Buy and Sell Stock 题目的意思:给予一个数组price,表示特定股票在某天的股价,里面第i个数表示第i天的价格.只 ...

  5. 用python帮朋友刷帖

    0x0前言: 答应了一个朋友帮他刷贴,自己用python写了一个脚本刷. 虽然行为不好..但是缺钱用... 0x01准备: splinter模块: chrome浏览器驱动 0x02开始: 1.进入百度 ...

  6. Python 自动刷博客浏览量

    哈哈,今天的话题有点那什么了哈.咱们应该秉承学习技术的角度来看,那么就开始今天的话题吧. 思路来源 今天很偶然的一个机会,听到别人在谈论现在的"刷量"行为,于是就激发了我的好奇心. ...

  7. Hasse神舟笔记本卡logo解决,刷BIOS方法,教你修复神船

    我的电脑是神舟战神K660E i7 d7的,前两天装Windows10,Ubuntu,MAC OS Mojave,PE 一堆操作,使用bootice重建uefi引导,结果在前几天,我删了一个重复的ue ...

  8. sony Z5P 刷rec、root的方法

    想root需要刷第三方recovery,刷recovery需要先解锁.但如果直接解锁,会丧失相机算法.屏幕超逼真模式,所以不能直接来. 大体步骤就是解完锁后自己做个内核刷进去,欺骗系统让他觉得没解锁. ...

  9. K2路由器刷机教程

    http://blog.sina.com.cn/s/blog_dc642faa0102x1on.html 方法:先降价——刷入breed——刷入固件 1.K2路由固件版本为V22.4.5.39 / V ...

随机推荐

  1. 数字巨头们的表态--<大佬与大话>

    作者魏武挥 类别非虚构 / 中篇 本书为作者为<21世纪商业评论>的专栏文章合集,共20篇,算是第一卷吧,后期还会写下去.这个专栏的名字叫<大佬与大话>,专门收集TMT圈子商业 ...

  2. grafana结合influxdb、open-falcon出图配置

    1.https://www.jianshu.com/p/fadcf4d92b0e 2.https://www.jianshu.com/p/21ce6ee143f3 3.http://www.super ...

  3. 杭电1863 畅通project

    畅通project Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. es中插入数据

    es中插入数据 学习了:https://www.imooc.com/video/15769/0 分为指定Id和自动生成Id两种: 1,指定Id使用PUT操作 PUT http://127.0.0.1: ...

  5. SpringCloud中Rabbitmq的使用

    1.pom配置,添加以来jar包 <dependency> <groupId>org.springframework.cloud</groupId> <art ...

  6. 浅析怎样学好C语言

    今天,我能够自称是一个混IT的人,并能以此谋生,将来大家能一次谋生.都要感谢两个人:克劳德.香农和约翰.冯.诺依曼,是他们发现了全部的数字化信息,不论是一段程序,一封email.一部电影都是用一连串的 ...

  7. HDU 3305 Ice-sugar Gourd

    Ice-sugar Gourd Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  8. [转载]php 数组 类对象 值传递 引用传递 区别

    一般的数据类型(int, float, bool)不做这方面的解说了 这里详细介绍一下数组和的类的对象作为参数进行值传递的区别 数组值传递 实例代码: <?php function main() ...

  9. C开发人员眼中的SICP学习

    谈谈自己看SICP的一些体会 第一章  构造过程抽象 这一章事实上和C语言全然等价, 不打算深入学习LISP的能够高速略过. 思想上没有太多新的东西. 这一章最核心的价值就是以下3句话, 理解了这一章 ...

  10. spi flash 操作

    W25Q16V 是华邦出的一颗 spi flash. 25系列是比较通用的一个系列. 后面的数字 16 跟容量有关, 16 表示 16Mbits, 相当于 2MB. 与此类似的还有 W25Q128V ...