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

看毛爷爷即将炖完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. iOS WKWebView添加网页加载进度条(转)

    一.效果展示 WKWebProgressViewDemo.gif 二.主要步骤 1.添加UIProgressView属性 @property (nonatomic, strong) WKWebView ...

  2. win10中显示wpcap.dll丢失的处理方式

    win10中显示wpcap.dll丢失的处理方式 学习了:https://jingyan.baidu.com/article/4f34706e30e673e387b56dd8.html 直接安装Win ...

  3. vc常用类总结(转载)

    常用类 CRect:用来表示矩形的类,拥有四个成员变量:top left bottom right.分别表是左上角和右下角的坐标.可以通过以下的方法构造: CRect( int l, int t, i ...

  4. Android——坐标系及转化

    一.坐标系 Android应用层坐标系原点在左上角,坐标范围(0,0)——(width,height). Android底层坐标系原点在屏幕中央,坐标范围(-1000,,1000)——(1000,10 ...

  5. MAC Intellij IDEA 经常使用快捷键(本人亲自測试过)

     MAC Intellij IDEA 经常使用快捷键 keymap 设置 MAC OS X 10.5+ alt+f7查找变量方法使用的地方 F3加入书签 Ctrl + O快捷覆写方法 Alt + F3 ...

  6. MapReduce简述、工作流程及新旧API对照

    什么是MapReduce? 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查而且数出有多少张是黑桃. MapReduce方法则是: 1. 给在座的全部玩家中分配这摞牌. 2. 让每一个玩家数自己手 ...

  7. C/C++用状态转移表联合函数指针数组实现状态机FSM

    状态机在project中使用很的频繁,有例如以下常见的三种实现方法: 1. switch-case 实现.适合简单的状态机. 2. 二维状态表state-event实现.逻辑清晰.可是矩阵通常比較稀疏 ...

  8. Unity3D游戏开发之粒子系统实现具体解释

     今天为大家分享的是Unity3D中的粒子系统.粒子系统通经常使用来表现烟雾.云等高级效果.是一个十分注重制作技巧的部分.今天我们将以一个气泡的演示实例来一起学习怎样在Unity3D中使用粒子系统 ...

  9. 【POJ3740】Easy Finding DLX(Dancing Links)精确覆盖问题

    题意:多组数据,每组数据给你几行数,要求选出当中几行.使得每一列都有且仅有一个1.询问是可不可行,或者说能不能找出来. 题解:1.暴搜.2.DLX(Dancing links). 本文写的是DLX. ...

  10. spring 相关博客

    Spring中使用Interceptor拦截器 spirng4   中文文档 ssm整合 Spring系列之Spring常用注解总结 Spring框架中context-param与servlet中in ...