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

看毛爷爷即将炖完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. MySQL 为日期增加一个时间间隔

    set @dt = now(); select date_add(@dt, interval 1 day);   - 加1天 select date_add(@dt, interval 1 hour) ...

  2. axis2调用WSDL接口

    public static JSONObject sendWsdl(String url,String xmlStr){ JSONObject res=new JSONObject(); try { ...

  3. 一个炫酷的Actionbar效果

    今天在网上看到一个炫酷的Actionbar效果,一个老外做的DEMO,目前很多流行的app已经加入了这个效果. 当用户初始进入该界面的时候,为一个透明的 ActiionBar ,这样利用充分的空间显示 ...

  4. oracle 静默安装

    下载oracle的安装包: 下载地址: 注意下载oracle是须要注冊oracle的 http://download.oracle.com/otn/nt/oracle11g 下载两个包: linux. ...

  5. 吃我一记咸鱼突刺——使用板载RTC定时开机

    前言 原创文章,转载引用务必注明链接.水平有限,欢迎指正. 2016年3月30日 Lemuntu(Base On Jessie) 3.10.37 原载于Lemaker论坛.汇总于此. 看ATC2603 ...

  6. HDU 3118 Arbiter 判定奇圈

    题目来源:pid=3118">HDU 3118 Arbiter 题意:翻译过来就是不能有奇圈 每走一步状态会变化 当他回到起点时假设和原来的状态不一样 可能会死 求至少去掉多少条边能够 ...

  7. memchached你知道和不知道的事

  8. java栈、堆

    一.栈.堆 几个小概念 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的 ...

  9. Codeforces 486E LIS of Sequence(线段树+LIS)

    题目链接:Codeforces 486E LIS of Sequence 题目大意:给定一个数组.如今要确定每一个位置上的数属于哪一种类型. 解题思路:先求出每一个位置选的情况下的最长LIS,由于開始 ...

  10. WebService Get/Post/Soap 方式请求

    import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.InputStream; im ...