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

看毛爷爷即将炖完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. Java服务器获取客户端的ip

    原文:http://www.open-open.com/code/view/1454133120089 /** * 获取登录用户IP地址 * * @param request * @return */ ...

  2. centos 7 卸載 mysql

    跟網上文章,安裝了一個mysqlwget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 記下卸載過程: 首先执行查看命令 ...

  3. python实现的一个简单的网页爬虫

    学习了下python,看了一个简单的网页爬虫:http://www.cnblogs.com/fnng/p/3576154.html 自己实现了一个简单的网页爬虫,获取豆瓣的最新电影信息. 爬虫主要是获 ...

  4. 封装算法: 模板方法(Template Method)模式

    template method(模板方法)模式是一种行为型设计模式.它在一个方法中定义了算法的骨架(这种方法被称为template method.模板方法),并将算法的详细步骤放到子类中去实现.tem ...

  5. 删除moduleCache下文件解决预编译头文件相关的编译错误

    之前有在代码全部正确的情况下,遇到过下面的编译错误: fatal error: file '.....h' has been modified since the precompiled header ...

  6. Struts2实现空表单信息的提示

    须要的jar包文件: index.jsp源代码: <%@ page language="java" contentType="text/html; charset= ...

  7. 【转载】FAT12文件系统之引导扇区结构

    FAT12文件系统之引导扇区结构 文件系统即文件管理系统,是操作系统的重要组成部分之一,如果需要开发底层磁盘驱动或编写自己的操作系统,就必须详细了解文件系统. FAT12是Microsoft公司DOS ...

  8. 1987年国际C语言混乱代码大赛获奖的一行代码

    macb() ? lpcbyu(&gbcq/_\021%ocq\012\0_=w(gbcq)/_dak._=}_ugb_[0q60)s+ 这是CoolShell博主之前做了一个非常有意思的在线 ...

  9. sanic官方文档解析之logging和request Data

    1,sanic的logging: Sanic允许有做不同类型的日志(通过的日志,错误的日志),在基于Python3的日志API接口请求,你必须具备基本的Python3的日志知识,在你如果想创建一个新的 ...

  10. var let Hositing const Temporal Dead Zone

    var  let  Hositing const Temporal Dead Zone 临时死区