5
10
2016
0

[BZOJ2626] JZPFAR

KD-Tree直接上

维护一个关于点对距离的数组

每次询问直接在KD-Tree里面贪心的找就可以了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int N=100005;
 
int Sort_Tag,n,m,root,Ask_k,id[25];
long long Ask_x,Ask_y,ans[25];
 
struct KDTree{
long long d[2],mx[2],mn[2];
int l,r,id;
friend bool operator<(KDTree A,KDTree B){
return (A.d[Sort_Tag]<B.d[Sort_Tag])||(A.d[Sort_Tag]==B.d[Sort_Tag] && A.d[!Sort_Tag]<B.d[!Sort_Tag]);
}
}tree[N],Tp;
 
void Pushup(int rt){
if(tree[rt].l){
    if(tree[rt].mn[0]>tree[tree[rt].l].mn[0])tree[rt].mn[0]=tree[tree[rt].l].mn[0];
    if(tree[rt].mn[1]>tree[tree[rt].l].mn[1])tree[rt].mn[1]=tree[tree[rt].l].mn[1];
    if(tree[rt].mx[0]<tree[tree[rt].l].mx[0])tree[rt].mx[0]=tree[tree[rt].l].mx[0];
    if(tree[rt].mx[1]<tree[tree[rt].l].mx[1])tree[rt].mx[1]=tree[tree[rt].l].mx[1];
}
if(tree[rt].r){
    if(tree[rt].mn[0]>tree[tree[rt].r].mn[0])tree[rt].mn[0]=tree[tree[rt].r].mn[0];
    if(tree[rt].mn[1]>tree[tree[rt].r].mn[1])tree[rt].mn[1]=tree[tree[rt].r].mn[1];
    if(tree[rt].mx[0]<tree[tree[rt].r].mx[0])tree[rt].mx[0]=tree[tree[rt].r].mx[0];
    if(tree[rt].mx[1]<tree[tree[rt].r].mx[1])tree[rt].mx[1]=tree[tree[rt].r].mx[1];
}
}
 
int Build(int l,int r,int D){
int mid=l+r>>1;
Sort_Tag=D;
nth_element(tree+l+1,tree+mid+1,tree+r+1);
tree[mid].mx[0]=tree[mid].mn[0]=tree[mid].d[0];
tree[mid].mx[1]=tree[mid].mn[1]=tree[mid].d[1];
if(l<mid)tree[mid].l=Build(l,mid-1,!D);
if(r>mid)tree[mid].r=Build(mid+1,r,!D);
Pushup(mid);
return mid;
}
 
long long Sqr(long long x){return x*x;}
 
long long MxDist(int p,long long x,long long y){
return max(Sqr(tree[p].mx[0]-x),Sqr(tree[p].mn[0]-x))+max(Sqr(tree[p].mx[1]-y),Sqr(tree[p].mn[1]-y));
}
 
void Query(int rt){
long long Dl,Dr,Dm=Sqr(tree[rt].d[0]-Ask_x)+Sqr(tree[rt].d[1]-Ask_y);
int Kt=Ask_k;
while(Kt && ((ans[Kt]<Dm)||(ans[Kt]==Dm && id[Kt]>tree[rt].id)))Kt--;
if(Kt!=Ask_k){
    for(int i=Ask_k;i>=Kt+2;i--){
        ans[i]=ans[i-1];
        id[i]=id[i-1];
    }
    ans[Kt+1]=Dm;id[Kt+1]=tree[rt].id;
}
if(tree[rt].l)Dl=MxDist(tree[rt].l,Ask_x,Ask_y);else Dl=-1;
if(tree[rt].r)Dr=MxDist(tree[rt].r,Ask_x,Ask_y);else Dr=-1;
if(Dl<Dr){
    if(Dr>=ans[Ask_k])Query(tree[rt].r);
    if(Dl>=ans[Ask_k])Query(tree[rt].l);
}
else {
    if(Dl>=ans[Ask_k])Query(tree[rt].l);
    if(Dr>=ans[Ask_k])Query(tree[rt].r);
}
}
 
int main(){
freopen("2626.in","r",stdin);
freopen("2626.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%lld %lld",&tree[i].d[0],&tree[i].d[1]);tree[i].id=i;}
root=Build(1,n,0);
scanf("%d",&m);
for(int i=1;i<=m;i++){
    scanf("%lld %lld %lld",&Ask_x,&Ask_y,&Ask_k);
    memset(ans,0,sizeof(ans));
    memset(id,127,sizeof(id));
    Query(root);
    printf("%d\n",id[Ask_k]);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ3626] [LNOI2014]LCA

首先我们可以离线做

考虑每次把一条链上的权值全部加上1,然后询问z到根的值就是这个LCA的和

然后离线排序树剖一下直接做就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int N=50005,Mod=201314;
 
int n,q,en,fa[N],h[N],cnt,dep[N],top[N],segn,siz[N],son[N],id[N];
 
struct Ask{
int z,ans1,ans2;
}Qu[N];
 
struct Option{
int id,p,flag;
friend bool operator<(Option A,Option B){return A.p<B.p;}
}Opt[2*N];
 
struct Edge{
int b,next;
}e[N];
 
void AddEdge(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
}
 
struct SegTree{
int l,r,sum,tag;
}tree[4*N];
 
void Pushup(int rt){tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%Mod;}
 
void Pushdown(int rt){
if(tree[rt].tag){
    tree[rt<<1].tag=(tree[rt<<1].tag+tree[rt].tag)%Mod;
    tree[rt<<1|1].tag=(tree[rt<<1|1].tag+tree[rt].tag)%Mod;
    tree[rt<<1].sum=(tree[rt<<1].sum+tree[rt].tag*(tree[rt<<1].r-tree[rt<<1].l+1))%Mod;
    tree[rt<<1|1].sum=(tree[rt<<1|1].sum+tree[rt].tag*(tree[rt<<1|1].r-tree[rt<<1|1].l+1))%Mod;
    tree[rt].tag=0;
}
}
 
void Build(int rt,int l,int r){
tree[rt].l=l;
tree[rt].r=r;
if(l==r){tree[rt].sum=0;tree[rt].tag=0;return;}
int mid=l+r>>1;
Build(rt<<1,l,mid);
Build(rt<<1|1,mid+1,r);
}
 
void Modify(int rt,int l,int r,int val){
if(l<=tree[rt].l && tree[rt].r<=r){
    tree[rt].tag=(tree[rt].tag+val)%Mod;
    tree[rt].sum=(tree[rt].sum+val*(tree[rt].r-tree[rt].l+1))%Mod;
    return;
}
Pushdown(rt);
int mid=tree[rt].l+tree[rt].r>>1;
if(l<=mid)Modify(rt<<1,l,r,val);
if(r>mid)Modify(rt<<1|1,l,r,val);
Pushup(rt);
}
 
int Query(int rt,int l,int r){
if(l<=tree[rt].l && tree[rt].r<=r)return tree[rt].sum;
int mid=tree[rt].l+tree[rt].r>>1,ans=0;
Pushdown(rt);
if(l<=mid)ans=(ans+Query(rt<<1,l,r))%Mod;
if(r>mid)ans=(ans+Query(rt<<1|1,l,r))%Mod;
return ans;
}
 
void dfs1(int u){
dep[u]=dep[fa[u]]+1;
siz[u]=1;
son[u]=0;
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(v==fa[u])continue;
    dfs1(v);
    siz[u]+=siz[v];
    if(siz[son[u]]<siz[v])son[u]=v;
}
}
 
void dfs2(int u,int ux){
top[u]=ux;
id[u]=++segn;
if(!son[u])return;
dfs2(son[u],ux);
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(son[u]==v || fa[u]==v)continue;
    dfs2(v,v);
}
}
 
void Update(int x){
while(top[x]!=top[1]){
    Modify(1,id[top[x]],id[x],1);
    x=fa[top[x]];
}
Modify(1,id[1],id[x],1);
}
 
int Solve(int x){
int ans=0;
while(top[x]!=top[1]){
    ans=(ans+Query(1,id[top[x]],id[x]))%Mod;
    x=fa[top[x]];
}
return (ans+Query(1,id[1],id[x]))%Mod;
}
 
int main(){
freopen("3626.in","r",stdin);
freopen("3626.out","w",stdout);
scanf("%d %d",&n,&q);
for(int i=2;i<=n;i++){scanf("%d",&fa[i]);fa[i]++;AddEdge(fa[i],i);}
dfs1(1);
dfs2(1,1);
Build(1,1,n);
for(int i=1;i<=q;i++){
    int x,y,z;
    scanf("%d %d %d",&x,&y,&z);
    x++;y++;z++;
    Qu[i].z=z;
    Opt[++cnt].id=i;
    Opt[cnt].p=x-1;
    Opt[cnt].flag=0;
    Opt[++cnt].id=i;
    Opt[cnt].p=y;
    Opt[cnt].flag=1;
}
sort(Opt+1,Opt+cnt+1);
int Now=1;
for(int i=1;i<=cnt;i++){
    while(Now<=Opt[i].p){Update(Now);Now++;}
    if(Opt[i].flag)Qu[Opt[i].id].ans2=Solve(Qu[Opt[i].id].z);
    else Qu[Opt[i].id].ans1=Solve(Qu[Opt[i].id].z);
}
for(int i=1;i<=q;i++){
    printf("%d\n",(Qu[i].ans2-Qu[i].ans1+Mod)%Mod);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ3223] Tyvj 1729 文艺平衡树

直接Splay上

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
 
const int N=100005;
 
int n,m,a[N];
 
struct Node{
int v,rev,siz;
Node *ch[2],*fa;
Node(){}
Node(int vx);
void Pushdown();
void Pushup();
}*root,*Null;
 
Node::Node(int vx){
v=vx;
siz=1;
rev=0;
ch[0]=ch[1]=fa=Null;
}
 
Node *GetNull(){
Node *p=new Node(0);
p->siz=0;
p->ch[0]=p->ch[1]=p->fa=p;
return p;
}
 
void Node::Pushdown(){
if(rev){
    rev=0;
    if(ch[0]!=Null)ch[0]->rev^=1;
    if(ch[1]!=Null)ch[1]->rev^=1;
    swap(ch[0]->ch[0],ch[0]->ch[1]);
    swap(ch[1]->ch[0],ch[1]->ch[1]);
}
}
 
void Node::Pushup(){
siz=ch[0]->siz+ch[1]->siz+1;
}
 
void Rotate(Node *x,int kind){
Node *y=x->fa,*z=y->fa;
y->ch[!kind]=x->ch[kind];
if(x->ch[kind]!=Null)x->ch[kind]->fa=y;
x->fa=z;
if(z!=Null)z->ch[z->ch[1]==y]=x;
y->fa=x;
x->ch[kind]=y;
y->Pushup();
x->Pushup();
}
 
void Splay(Node *x,Node *place){
while(x->fa!=place){
    Node *y=x->fa,*z=y->fa;
    if(z==place)Rotate(x,y->ch[0]==x);
    else {
        if(y->ch[0]==x && z->ch[0]==y){Rotate(y,1);Rotate(x,1);}
        else if(y->ch[0]==x && z->ch[1]==y){Rotate(x,1);Rotate(x,0);}
        else if(y->ch[1]==x && z->ch[0]==y){Rotate(x,0);Rotate(x,1);}
        else {Rotate(y,0);Rotate(x,0);}
    }
}
if(place==Null)root=x;
}
 
Node *Find(Node *splay,int k){
splay->Pushdown();
if(splay->ch[0]->siz+1==k)return splay;
if(splay->ch[0]->siz>=k)return Find(splay->ch[0],k);
return Find(splay->ch[1],k-1-splay->ch[0]->siz);
}
 
Node *GetSeq(int l,int r){
Node *Tp1=Find(root,l);
Splay(Tp1,Null);
Node *Tp2=Find(root,r+2);
Splay(Tp2,root);
return Tp2->ch[0];
}
 
Node *Build(int l,int r){
if(l>r)return Null;
int mid=l+r>>1;
Node *splay=new Node(a[mid]);
splay->ch[0]=Build(l,mid-1);
if(splay->ch[0]!=Null)splay->ch[0]->fa=splay;
splay->ch[1]=Build(mid+1,r);
if(splay->ch[1]!=Null)splay->ch[1]->fa=splay;
splay->Pushup();
return splay;
}
 
void PrintTree(Node *rt){
if(rt==Null)return;
rt->Pushdown();
if(rt->ch[0]!=Null)PrintTree(rt->ch[0]);
if(rt->v)printf("%d ",rt->v);
if(rt->ch[1]!=Null)PrintTree(rt->ch[1]);
}
 
void Reverse(int l,int r){
Node *seq=GetSeq(l,r),*fat=seq->fa;
seq->rev^=1;
swap(seq->ch[0],seq->ch[1]);
fat->Pushup();
fat->fa->Pushup();
}
 
int main(){
freopen("3223.in","r",stdin);
freopen("3223.out","w",stdout);
scanf("%d %d",&n,&m);
Null=GetNull();
for(int i=1;i<=n;i++)a[i+1]=i;
root=Build(1,n+2);
for(int i=1;i<=m;i++){
    int l,r;
    scanf("%d %d",&l,&r);
    Reverse(l,r);
}
PrintTree(root);
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ2739] 最远点

四边形不等式优化

我一开始直接写了一个旋转卡壳然后WA了

搜了一下题解,发现这样不对(有可能点会靠后一些)

需要优化

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
 
const int N=500005;
int n,T,ans[N];
 
struct Point{
long long x,y,id;
Point(){}
Point(long long sa,long long sb){x=sa;y=sb;}
friend Point operator+(Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
friend Point operator-(Point A,Point B){return Point(A.x-B.x,A.y+B.y);}
friend Point operator*(Point A,long long B){return Point(A.x*B,A.y*B);}
friend long long operator*(Point A,Point B){return A.x*B.y-A.y*B.x;}
}poi[2*N];
 
long long Dist(Point A,Point B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
 
bool cmp(int i,int j,int k){
long long x=Dist(poi[i],poi[j]),y=Dist(poi[i],poi[k]);
if(j<i || j>i+n)x=-x;
if(k<i || k>i+n)y=-y;
return x==y?poi[j].id>poi[k].id:x<y;
}
 
void Find(int l,int r,int L,int R){
if(l>r)return;
int mid=l+r>>1,M=L;
for(int i=L+1;i<=R;i++)if(cmp(mid,M,i))M=i;
ans[mid]=poi[M].id;
Find(l,mid-1,L,M);Find(mid+1,r,M,R);
}
 
int main(){
freopen("2739.in","r",stdin);
freopen("2739.out","w",stdout);
scanf("%d",&T);
while(T--){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld %lld",&poi[i].x,&poi[i].y),poi[i].id=i;
    if(n==1){puts("1");continue;}
    if(n==2){puts("2\n1");continue;}
    for(int i=n+1;i<=2*n;i++)poi[i]=poi[i-n];
    Find(1,n,1,n<<1);
    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ2177] 曼哈顿最小生成树

模版题

每个点只向每个象限里最近的点连边

离散化后树状数组维护就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const long long N=50005,LIMIT=1000000000,INF=210000000000000ll;
 
long long n,f[N],Fir[10*N],Sec[10*N],cnt,Line[10*N],Num[10*N],tot,ans;
 
struct Point{
long long x,y,id;
friend bool operator<(Point A,Point B){return (A.x<B.x)|(A.x==B.x && A.y<B.y);}
}poi[N];
 
struct Edge{
long long x,y,len;
Edge(){}
Edge(long long sa,long long sb,long long sc){x=sa;y=sb;len=sc;}
friend bool operator<(Edge A,Edge B){return A.len<B.len;}
}e[20*N];
 
long long Find(long long x){return f[x]==x?x:f[x]=Find(f[x]);}
void Union(long long x,long long y){if(x>y)f[x]=y;else f[y]=x;}
long long lowbit(long long x){return x&(-x);}
void AddBIT(long long x,long long y,long long z){while(x){if(Fir[x]>y){Fir[x]=y;Sec[x]=z;}x-=lowbit(x);}}
long long QueBIT(long long x){long long Mx=LIMIT*2,Ex=0;while(x<=n){if(Mx>Fir[x]){Mx=Fir[x];Ex=Sec[x];}x+=lowbit(x);}return Ex;}
long long Abs(long long x){return x>0?x:-x;}
long long Dist(Point A,Point B){return Abs(A.y-B.y)+Abs(A.x-B.x);}
 
int main(){
freopen("2177.in","r",stdin);
freopen("2177.out","w",stdout);
scanf("%lld",&n);
for(long long i=1;i<=n;i++){scanf("%lld %lld",&poi[i].x,&poi[i].y);poi[i].id=i;}
for(long long i=1;i<=4;i++){
    if(i==3)for(long long i=1;i<=n;i++)poi[i].x=LIMIT-poi[i].x;
    if(i==2 || i==4)for(long long i=1;i<=n;i++)swap(poi[i].x,poi[i].y);
    sort(poi+1,poi+n+1);
    for(long long i=1;i<=n;i++)Line[i]=poi[i].y-poi[i].x;
    sort(Line+1,Line+n+1);
    for(long long i=1;i<=n;i++)Num[i]=lower_bound(Line+1,Line+n+1,poi[i].y-poi[i].x)-Line;
    for(long long i=1;i<=n;i++)Fir[i]=INF;
    for(long long i=n;i>=1;i--){
        long long Set=QueBIT(Num[i]);
        if(Set)e[++cnt]=Edge(poi[i].id,poi[Set].id,Dist(poi[i],poi[Set]));
        AddBIT(Num[i],poi[i].y+poi[i].x,i);
    }
}
sort(e+1,e+cnt+1);
for(long long i=1;i<=n;i++)f[i]=i;
for(long long i=1;i<=cnt && tot<n-1;i++){
    if(Find(e[i].x)!=Find(e[i].y)){
        tot++;
        Union(Find(e[i].x),Find(e[i].y));
        ans+=1ll*e[i].len;
    }
}
printf("%lld\n",ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ1415] [Noi2005]聪聪和可可

图上进行概率DP

先BFSn次算出每个点的最优前进点

然后对于每种情况DFS算期望

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
 
const int N=1005;
 
int n,m,en,h[N],deg[N],Cat,Mouse,D[N][N],P[N][N];
double f[N][N];
queue<int> Q;
 
struct Edge{
int b,next;
}e[N*2];
 
void AddEdge(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
deg[sa]++;
}
 
void BFS(int S){
Q.push(S);
D[S][S]=0;
while(!Q.empty()){
    int u=Q.front(),tmp=P[S][u];
    Q.pop();
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].b;
        if(D[S][v]==-1 || (D[S][u]+1==D[S][v] && tmp<P[S][v])){
            D[S][v]=D[S][u]+1;
            if(!tmp)P[S][v]=v;
            else P[S][v]=tmp;
            Q.push(v);
        }
    }
}
}
 
double DP(int Cat,int Mouse){
if(f[Cat][Mouse])return f[Cat][Mouse];
if(Cat==Mouse)return f[Cat][Mouse]=0;
if(P[Cat][Mouse]==Mouse || P[P[Cat][Mouse]][Mouse]==Mouse)return f[Cat][Mouse]=1;
double Sum=DP(P[P[Cat][Mouse]][Mouse],Mouse);
for(int i=h[Mouse];i;i=e[i].next)Sum+=DP(P[P[Cat][Mouse]][Mouse],e[i].b);
return f[Cat][Mouse]=Sum/(deg[Mouse]+1)+1;
}
 
int main(){
freopen("1415.in","r",stdin);
freopen("1415.out","w",stdout);
memset(D,-1,sizeof(D));
scanf("%d %d %d %d",&n,&m,&Cat,&Mouse);
for(int i=1;i<=m;i++){
    int sa,sb;
    scanf("%d %d",&sa,&sb);
    AddEdge(sa,sb);
    AddEdge(sb,sa);
}
for(int i=1;i<=n;i++)BFS(i);
printf("%.3lf\n",DP(Cat,Mouse));
return 0;
}
Category: BZOJ | Tags: OI bzoj
5
10
2016
0

[BZOJ3000] Big Number

使用n!近似公式算一下就可以了

注意特判

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
 
const long double Pi=acos(-1),e=exp(1),eps=1e-10;
long long n,k;
 
long double log(long double a,long double b){return log(a)/log(b);}
 
int main(){
freopen("3000.in","r",stdin);
freopen("3000.out","w",stdout);
while(scanf("%lld %lld",&n,&k)!=EOF){
    double ans=0;
    if(n<=10000){
        for(int i=1;i<=n;i++)ans+=log(i);
        ans/=log(k);
        ans=ceil(ans+eps);
        printf("%.0lf\n",ans);
    }
    else printf("%lld\n",(long long)(0.5*log(2*Pi*n,k)+n*log(n,k)-n*log(e,k)+1));
}
return 0;
}
Category: BZOJ | Tags: OI bzoj
4
30
2016
0

后缀数组练习

CTSC&APIO感觉自己水平太低,完全没法做……

所以打算利用在北京的这段时间提高一下自己的OI水平

后缀数组虽然会写,但是仅限于会敲模版。。

所以我打算把罗穗骞论文里面的所有题写一遍

----------------------------------------

POJ 2774

两个串连一起搞完后缀数组然后求height最大值判断一下前后是否分别属于两个不同的串就好了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=200005;

int n1,n2,n,rank[N],sa[N],rank2[N],wa[N],ws[N],height[N];
char s1[N],s2[N],s[2*N];

int cmp(int *r,int a,int b,int l){return (r[a]==r[b])&(r[a+l]==r[b+l]);}

void GetSA(char *r,int *sa,int n,int m){
int i,j,p,*x=rank,*y=rank2,*t;
for(i=0;i<m;i++)ws[i]=0;
for(i=0;i<n;i++)ws[x[i]=r[i]]++;
for(i=1;i<m;i++)ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--)sa[--ws[x[i]]]=i;
for(j=p=1;p<n;j<<=1,m=p){
	for(p=0,i=n-j;i<n;i++)y[p++]=i;
	for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
	for(i=0;i<m;i++)ws[i]=0;
	for(i=0;i<n;i++)ws[wa[i]=x[y[i]]]++;
    for(i=1;i<m;i++)ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--)sa[--ws[wa[i]]]=y[i];
    for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}

void CalHeight(char *r,int *sa,int n){
int i,j,k=0;
for(i=1;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;height[rank[i++]]=k){
	for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
}

bool Diff(int x){return (sa[x]<n1 && sa[x-1]>=n1)||(sa[x]>=n1 && sa[x-1]<n1);}

int Solve(){
int MxHeight=0;
for(int i=2;i<=n;i++){
	if(height[i]>MxHeight && Diff(i))MxHeight=height[i];
}
return MxHeight;
}

int main(){
freopen("2774.in","r",stdin);
freopen("2774.out","w",stdout);
scanf("%s %s",s1,s2);
n1=strlen(s1);
n2=strlen(s2);
n=n1+n2;
for(int i=0;i<n1;i++)s[i]=s1[i];
for(int i=n1;i<n;i++)s[i]=s2[i-n1];
s[n]=0;
GetSA(s,sa,n+1,128);
CalHeight(s,sa,n);
printf("%d\n",Solve());
return 0;
}

----------------------------------------

POJ 1743

先差分,然后二分答案k,然后对于height分组(height[i]记录的是sa[i]和sa[i-1]的LCP),那么因为字典序相邻的后缀在sa里的顺序是连续的,那么我们对于判定答案k是否合法的方法就是找到连续的height,它们的值都不小于k(保证重复的串长大于等于k),然后如果组内最靠前和最靠后的位置差也大于等于k,那么这个方案就是合法的。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;

const int N=200005,INF=2100000000;

int sa[N],rank[N],rank2[N],ws[N],s[N],wa[N],n,height[N];

int Abs(int x){return x>0?x:-x;}
int cmp(int *r,int a,int b,int l){return (r[a]==r[b])&(r[a+l]==r[b+l]);}

void GetSA(int *r,int *sa,int n,int m){
int i,j,p,*x=rank,*y=rank2,*t;
for(i=0;i<m;i++)ws[i]=0;
for(i=0;i<n;i++)ws[x[i]=r[i]]++;
for(i=1;i<m;i++)ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--)sa[--ws[x[i]]]=i;
for(j=p=1;p<n;j<<=1,m=p){
    for(p=0,i=n-j;i<n;i++)y[p++]=i;
    for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
    for(i=0;i<m;i++)ws[i]=0;
    for(i=0;i<n;i++)ws[wa[i]=x[y[i]]]++;
    for(i=1;i<m;i++)ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--)sa[--ws[wa[i]]]=y[i];
    for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}

void Calheight(int *r,int *sa,int n){
int i,j,k=0;
for(i=1;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;height[rank[i++]]=k){
    for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
}

int Solve(int k){
int i=2,Mx,Mn;
while(1){
    while(i<=n && height[i]<k)i++;
    if(i>n)break;
    Mx=sa[i-1];Mn=sa[i-1];
    while(i<=n && height[i]>=k){Mn=min(Mn,sa[i]);Mx=max(Mx,sa[i]);i++;}
    if(Mx-Mn>=k)return 1;
}
return 0;
}

int Div(){
int l=4,r=n*2,ans=0;
while(l<=r){
    int mid=l+r>>1;
    if(Solve(mid)){l=mid+1;ans=mid;}
    else r=mid-1;
}
ans++;
return ans<5?0:ans;
}

int main(){
freopen("1743.in","r",stdin);
freopen("1743.out","w",stdout);
while(scanf("%d",&n),n){
    for(int i=0;i<n;i++)scanf("%d",&s[i]);
    if(n<10){puts("0");continue;}
    n--;
    for(int i=0;i<n;i++)s[i]=s[i+1]-s[i]+89;
    s[n]=0;
    for(int i=0;i<N;i++)wa[i]=ws[i]=0;
    GetSA(s,sa,n+1,200);
    Calheight(s,sa,n);
    printf("%d\n",Div());
}
return 0;
}

----------------------------------------

Category: OI | Tags: OI
4
30
2016
0

[BZOJ4519] [Cqoi2016]不同的最小割

map直接上

其他同ZJOI2011 最小割

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<cstdlib>
using namespace std;
 
const int N=8505,P=855;
const long long INF=210000000000000ll;
 
int n,m,en,h[P],mark[P],cur[P],level[P],S,T,a[P],tmp[P],Ans;
long long ans[P][P];
queue<int> Q;
map<long long,int> Mp;
 
struct Edge{
int b,next,back;
long long f;
}e[N*4];
 
void AddEdge(int sa,int sb,long long sc){
e[++en].b=sb;
e[en].f=sc;
e[en].back=en+1;
e[en].next=h[sa];
h[sa]=en;
swap(sa,sb);
e[++en].b=sb;
e[en].f=0;
e[en].back=en-1;
e[en].next=h[sa];
h[sa]=en;
}
 
int BFS(){
memset(level,0,sizeof(level));
level[S]=1;
Q.push(S);
while(!Q.empty()){
    int u=Q.front();
    Q.pop();
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].b;
        if(level[v] || !e[i].f)continue;
        level[v]=level[u]+1;
        Q.push(v);
    }
}
return level[T];
}
 
long long DFS(int u,long long flow){
if(u==T)return flow;
long long f=flow;
for(int &i=cur[u];i;i=e[i].next){
    int v=e[i].b;
    long long fl;
    if(level[v]==level[u]+1 && e[i].f && (fl=DFS(v,min(f,e[i].f)))){
        e[i].f-=fl;
        e[e[i].back].f+=fl;
        f-=fl;
        if(f==0)return flow;
    }
}
return flow-f;
}
 
long long Dinic(){
long long ans=0;
while(BFS()){for(int i=1;i<=n;i++)cur[i]=h[i];ans+=DFS(S,INF);}
return ans;
}
 
void Rebuild(){
for(int i=1;i<=en;i+=2){
    e[i].f=e[i].f+e[i+1].f;
    e[i+1].f=0;
}
}
 
void dfs(int u){
mark[u]=1;
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(e[i].f && !mark[v])dfs(v);
}
}
 
void Solve(int l,int r){
if(l==r)return;
Rebuild();S=a[l];T=a[r];
long long flow=Dinic();
int L=l,R=r;
memset(mark,0,sizeof(mark));
dfs(S);
for(int i=1;i<=n;i++){
    if(!mark[i])continue;
    for(int j=1;j<=n;j++){
        if(!mark[j])ans[i][j]=ans[j][i]=min(ans[i][j],flow);
    }
}
for(int i=l;i<=r;i++){if(mark[a[i]])tmp[L++]=a[i];else tmp[R--]=a[i];}
for(int i=l;i<=r;i++)a[i]=tmp[i];
Solve(l,L-1);Solve(R+1,r);
}
 
int main(){
scanf("%d %d",&n,&m);
memset(ans,127,sizeof(ans));
for(int i=1;i<=n;i++)a[i]=i;
for(int i=1;i<=m;i++){
    int sa,sb;
    long long sc;
    scanf("%d %d %lld",&sa,&sb,&sc);
    AddEdge(sa,sb,sc);
    AddEdge(sb,sa,sc);
}
Solve(1,n);
for(int i=1;i<=n;i++){
    for(int j=i+1;j<=n;j++){
        if(Mp[ans[i][j]]==0){
            Mp[ans[i][j]]=1;
            Ans++;
        }
    }
}
printf("%d\n",Ans);
return 0;
}
Category: BZOJ | Tags: OI bzoj
4
30
2016
0

[BZOJ2229] [Zjoi2011]最小割

这题我写了很长很长时间。。。

SB错误1:无向图要建双向边,然而我只建了单向边……

SB"错误"2:要加当前弧优化!一开始偷懒没加,然后TLE了N次

分治最小割,直接上Gusfield算法

顺便庆祝lyz lyf wyx cjy大爷签了PKU一本线 太神了orzzzzzzzzzzzzz

我这种蒟蒻ZJOI完全不敢去……

要补一补ZJOI讲课的Gusfield和Stoer-wanger算法了

为什么重建边时直接均分流量是对的啊……我按照正常方法写的然后跑的奇慢无比

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;

const int N=3005,P=155;
const long long INF=210000000000000ll;

int n,m,en,h[P],q,level[P],S,T,a[P],mark[P],tmp[P],Data_Num,cur[P];
long long ans[P][P];
queue<int> Q;

struct Edges{
int a,b;
long long v;
}es[N];

struct Edge{
int b,next,back;
long long f;
}e[N*4];

void AddEdge(int sa,int sb,long long sc){
e[++en].b=sb;
e[en].f=sc;
e[en].back=en+1;
e[en].next=h[sa];
h[sa]=en;
swap(sa,sb);
e[++en].b=sb;
e[en].f=0;
e[en].back=en-1;
e[en].next=h[sa];
h[sa]=en;
}

int BFS(){
memset(level,0,sizeof(level));
Q.push(S);
level[S]=1;
while(!Q.empty()){
	int u=Q.front();
	Q.pop();
    for(int i=h[u];i;i=e[i].next){
		int v=e[i].b;
		if(level[v] || !e[i].f)continue;
        level[v]=level[u]+1;
        Q.push(v);
    }
}
return level[T];
}

long long DFS(int u,long long flow){
if(u==T)return flow;
long long f=flow;
for(int &i=cur[u];i;i=e[i].next){
    int v=e[i].b;
    long long fl;
    if(level[u]+1==level[v] && e[i].f && (fl=DFS(v,min(f,e[i].f)))){
		e[i].f-=fl;
		e[e[i].back].f+=fl;
        f-=fl;
        if(f==0)return flow;
    }
}
return flow-f;
}

long long Dinic(){
long long ans=0;
while(BFS()){for(int i=1;i<=n;i++)cur[i]=h[i];ans+=DFS(S,INF);}
return ans;
}

void dfs(int u){
mark[u]=1;
for(int i=h[u];i;i=e[i].next){
	int v=e[i].b;
	if(e[i].f && !mark[v])dfs(v);
}
}

void Build(){
en=0;
memset(h,0,sizeof(h));
for(int i=1;i<=m;i++)AddEdge(es[i].a,es[i].b,es[i].v),AddEdge(es[i].b,es[i].a,es[i].v);;
}

void Rebuild(){
for(int i=1;i<=en;i+=2){e[i].f=e[i+1].f+e[i].f;e[i+1].f=0;}
}

void Solve(int l,int r){
if(l==r)return;
Rebuild();S=a[l];T=a[r];
long long flow=Dinic();
int L=l,R=r;
memset(mark,0,sizeof(mark));
dfs(S);
for(int i=1;i<=n;i++){
	if(!mark[i])continue;
	for(int j=1;j<=n;j++){
		if(!mark[j])ans[i][j]=ans[j][i]=min(ans[i][j],flow);
	}
}
for(int i=l;i<=r;i++){
	if(mark[a[i]])tmp[L++]=a[i];
	else tmp[R--]=a[i];
}
for(int i=l;i<=r;i++)a[i]=tmp[i];
Solve(l,L-1);Solve(R+1,r);
}

int main(){
freopen("2229.in","r",stdin);
freopen("2229.out","w",stdout);
scanf("%d",&Data_Num);
while(Data_Num--){
	memset(ans,127,sizeof(ans));
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d %d %lld",&es[i].a,&es[i].b,&es[i].v);
	for(int i=1;i<=n;i++)a[i]=i;
	Build();
	Solve(1,n);
	scanf("%d",&q);
	while(q--){
		int Ans=0;
		long long x;
		scanf("%lld",&x);
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				if(ans[i][j]<=x)Ans++;
			}
		}
		printf("%d\n",Ans);
	}
	puts("");
}
return 0;
}
Category: BZOJ | Tags: OI bzoj

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com