ZJOI2016

首先做了T2的旅行者,看到bz上面过的人数比较多。。

考试的时候完全没有想太多。一闪而过了分块思想,然后就没有然后了。。

大视野上面有题解,竟然是一个初中生写的。。?

正解其实是“分治”,每次选择中轴线,不会势能分析,感觉考场上想出来也肯定不敢打。。

#include<cstdio>
#include<algorithm>
#define inf 1000000000
#define N 100010
using namespace std;
int dis[N],ans[N],q[N],id[N],vet[N],head[N],next[N],pri[N];
int edgenum,cas,cnt,n,m;
struct node{int x1,y1,x2,y2,id;}a[N],b[N];
void add(int u,int v,int w)
{
  edgenum++;vet[edgenum]=v;next[edgenum]=head[u];
  head[u]=edgenum;pri[edgenum]=w;
  //printf("%d %d %d\n",u,v,w);
}
void push_down(int k)
{
  while(k*2<=cnt)
  {
     int k1=q[k],k2=q[k*2],k3=q[k*2+1];
     if(k*2+1<=cnt&&dis[k1]>dis[k3]&&dis[k3]<dis[k2])
     {
       id[k1]=k*2+1;id[k3]=k;swap(q[k],q[k*2+1]);
       k=k*2+1;
     }else if(dis[k1]>dis[k2])
     {
       id[k1]=k*2;id[k2]=k;swap(q[k],q[k*2]);k=k*2;
     }else break;
  }
}
void push_up(int k)
{
  while(k/2>0&&dis[q[k]]<dis[q[k/2]])
  {
    id[q[k]]=k/2;id[q[k/2]]=k;swap(q[k],q[k/2]);
    k=k/2;
  }
}
void dijk(int sta,int x1,int x2,int y1,int y2)
{
  cnt=1;q[1]=sta;id[sta]=1;dis[sta]=0;
  for(int i=x1;i<=x2;i++)
    for(int j=y1;j<=y2;j++)
     {
       int u=(i-1)*m+j;
       if(u!=sta){dis[u]=inf;q[++cnt]=u;id[u]=cnt;}
     }
  while(cnt)
  {
     int u=q[1];q[1]=q[cnt--];id[q[1]]=1;push_down(1);int e=head[u];//printf("reng=%d\n",u);
     while(e>0)
     {
       int v=vet[e],xx=(v-(v%m))/m+1,yy=v%m;if(yy==0)yy=m;if(v%m==0)xx--;
       //printf("ok=%d %d %d\n",v,xx,yy);
       if(xx>=x1&&xx<=x2&&yy>=y1&&yy<=y2)
       if(dis[v]>dis[u]+pri[e])
       {

         dis[v]=dis[u]+pri[e];
         //printf("ok=%d %d %d\n",u,v,dis[v]);
         push_up(id[v]);
       }
       e=next[e];
     }
  }
  //printf("sta=%d\n",sta);
  for(int i=x1;i<=x2;i++)
    for(int j=y1;j<=y2;j++)
     {
       int u=(i-1)*m+j;
       //printf("dis=%d %d\n",u,dis[u]);
     }
}
void solve(int x1,int x2,int y1,int y2,int l,int r)
{
  if(l>r)return;int mid;
  if(x2-x1>y2-y1)
  {
    mid=(x1+x2)>>1;
    for(int i=y1;i<=y2;i++)
    {
      int u=(mid-1)*m+i;dijk(u,x1,x2,y1,y2);
      for(int j=l;j<=r;j++)
      {
        int u1=(a[j].x1-1)*m+a[j].y1,u2=(a[j].x2-1)*m+a[j].y2;
        int t=dis[u1]+dis[u2];
        ans[a[j].id]=min(ans[a[j].id],t);
      }
    }
      int j=l-1,k=r+1;
      for(int i=l;i<=r;i++)if(a[i].x1<mid&&a[i].x2<mid)b[++j]=a[i];else
                           if(a[i].x1>mid&&a[i].x2>mid)b[--k]=a[i];
      for(int i=l;i<=j;i++)a[i]=b[i];solve(x1,mid-1,y1,y2,l,j);
      for(int i=k;i<=r;i++)a[i]=b[i];solve(mid+1,x2,y1,y2,k,r);
  }else
  {
    mid=(y1+y2)>>1;
    for(int i=x1;i<=x2;i++)
    {
      int u=(i-1)*m+mid;dijk(u,x1,x2,y1,y2);
      for(int j=l;j<=r;j++)
      {
        int u1=(a[j].x1-1)*m+a[j].y1,u2=(a[j].x2-1)*m+a[j].y2;
        int t=dis[u1]+dis[u2];
        ans[a[j].id]=min(ans[a[j].id],t);
      }
    }
      int j=l-1,k=r+1;
      for(int i=l;i<=r;i++)if(a[i].y1<mid&&a[i].y2<mid)b[++j]=a[i];else
                           if(a[i].y1>mid&&a[i].y2>mid)b[--k]=a[i];
      for(int i=l;i<=j;i++)a[i]=b[i];solve(x1,x2,y1,mid-1,l,j);
      for(int i=k;i<=r;i++)a[i]=b[i];solve(x1,x2,mid+1,y2,k,r);
  }
}
int main()
{
freopen("4456.in","r",stdin);
freopen("4456.out","w",stdout);
  scanf("%d %d",&n,&m);
  for(int i=1;i<=n;i++)
   for(int j=1;j<m;j++)
    {
      int x,u=(i-1)*m+j,v=(i-1)*m+j+1;scanf("%d",&x);
      add(u,v,x);add(v,u,x);
    }

  for(int i=1;i<n;i++)
   for(int j=1;j<=m;j++)
    {
      int x,u=(i-1)*m+j,v=i*m+j;scanf("%d",&x);
      add(u,v,x);add(v,u,x);
    }
  scanf("%d",&cas);
  for(int i=1;i<=cas;i++)
  {
    scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
    a[i].id=i;ans[i]=inf;
  }
  solve(1,n,1,m,1,cas);
  for(int i=1;i<=cas;i++)printf("%d\n",ans[i]);
} 
时间: 2024-10-16 12:51:52

ZJOI2016的相关文章

4455[Zjoi2016]小星星 容斥+dp

4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 527  Solved: 317[Submit][Status][Discuss] Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但 通过这些细线,这颗小星星还是被串在一起,也就是这

uoj #185. 【ZJOI2016】小星星

#185. [ZJOI2016]小星星 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有 nn 颗小星星,用 mm 条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了 n−1n−1 条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树. 小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星.如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上

[BZOJ4455][ZJOI2016]数星星(容斥DP)

4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 707  Solved: 419[Submit][Status][Discuss] Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但 通过这些细线,这颗小星星还是被串在一起,也就是这

[ZJOI2016]小星星&amp;[SHOI2016]黑暗前的幻想乡(容斥)

这两道题思路比较像,所以把他们放到一块. [ZJOI2016]小星星 题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星. 有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n-1条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树.小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星.如果现在饰品中两颗小星星有细线相连,那么要求对应的

bzoj4456 [Zjoi2016]旅行者

Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n×m个路口 (i,j)(1≤i≤n,1≤j≤m).她发现不同的道路路况不同,所以通过不同的路口需要不同的时间.通过调查发现,从路口(i,j)到路口(i,j+1)需要时间 r(i,j),从路口(i,j)到路口(i+1,j)需要时间c(i,j).注意这里的道路是双向的.小Y有q个询问,她想知道从路口(x1,y1)到路口(x2,y2)最少需要花多少

BZOJ4574 [Zjoi2016]线段树

比较厉害的dp. 网上题解都是利用了随机的条件,用了一个$O(n^4)$的dp,这里简单说一下. 用f(x,i,l,r)表示经过前i轮操作,[l,r]的所有数<=x,且l-1和r+1都>x的方案数. 转移:f(x,i,l,r)=f(x,i-1,l,r)*g(l,r)+f(x,i-1,j,r)*(j-1)+f(x,i-1,l,k)*(n-k),j<l,k>r 其中,g(l,r)=l*(l-1)/2+(r-l+1)*(r-l+2)/2+(n-r)*(n-r+1)/2 用个前缀和优化一下

BZOJ4573 : [Zjoi2016]大森林

扫描线,从左到右依次处理每棵树. 用set按时间顺序维护影响了这棵树的所有操作,那么一个点的父亲就是它前面第一个操作1. 用Splay维护树的括号序列,那么两点间的距离就是括号数量减去匹配的括号个数. 添加或删除操作0就是单点换父亲,添加或删除操作1就是区间换父亲.可以通过添加虚点来实现区间换父亲操作. 时间复杂度$O(m\log m)$. #include<cstdio> #include<algorithm> #include<set> using namespac

[ZJOI2016]小星星

题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星. 有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树.小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星.如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连.小Y想知道有多少种可能的对应方式. 只

bzoj4455【ZJOI2016】小星星

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4455 给一张图和该图的一棵生成树,求可能的编号方案数 sol  :dalao教导我们,看到计数想容斥 考虑对点i标号,O(2^n)枚举可以标的顶点,然后进行树形dp f[i][j]表示点i标j号的方案数,容斥一发即可 最后答案为∑f[1][i],记得开longlong #include<iostream> #include<algorithm> #include<cstd

BZOJ4455: [Zjoi2016]小星星

Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但 通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树.小Y找到了这个饰品的设 计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星.如果现在饰品中两颗小星星有细线相连, 那么要求对应的小星星原来的图纸上也有细线相连.小Y想知道有多少种