• 9.8<2>题解


    T1

    考场上以为是线段不能重叠,以至于我推了很久都没有结果,样例不是小的没意义,就是大的手玩不出来,然后我就死了

    题解告诉我们他是直线,他用了向量来解释,对于方向向量$(a,b)$,这个方向可以做贡献,一个限制就是$gcd(a,b)=1$,然后就是这个方向有几条直线,如果定义一个点$(x,y)$的前驱为$(x-a,y-b)$,后继为$(x+a,y+b)$,那符合条件的直线的数量就是满足前驱在点阵中,后继不在点阵中的点的数量,然后题解就告诉我说

    然而他并没有告诉我经过了什么样的计算,我们来理解一下,前面$(n-a){ imes}(m-b)$是所有的前驱在点阵中的点的数量,然后就是刨去后继也在点阵中的点的数量,那其实就是一个点找两个前驱,他的两个前驱都在点阵中的点的数量,那肯定就是$(n-2{ imes}a){ imes}(m-2{ imes}b)$,计算这个东西还是需要$O(n^2)$枚举$a$和$b$,$T$又很大,还是过不去,所以说我们选择前缀和优化他,拆成4个前缀和就可以做了,但是,这个毒瘤出题人他卡空间,然后我就不知道怎么办了,然后就是疯狂${\%}{\%}{\%}{\%}{\%}Smily$,我们发现每个前缀和对答案做贡献都可以是独立的所以,我们用一个前缀和,统计一次答案,清一次,就刚好可以卡过去了。。。。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cmath>
      5 #define maxn 4010
      6 #define maxm 10100
      7 #define ll long long
      8 #define mod 1073741824
      9 using namespace std;
     10 struct node{
     11     int n,m;
     12     ll ans;
     13 }q[maxm];
     14 int T,maxxn,maxxm;
     15 ll ans,ls;
     16 int a[maxn][maxn];
     17 bool g[maxn][maxn];
     18 bool gcd(int x,int y)
     19 {
     20     if(x%2==0&&y%2==0)  return 0;
     21     while(1)
     22     {
     23         if(x==1||y==1)  return 1;
     24         if(x==0||y==0)  return 0;
     25         while(x%2==0)  x/=2;
     26         while(y%2==0)  y/=2;
     27         if(x<y)  swap(x,y);
     28         x-=y;
     29     }
     30 }
     31 inline int read()
     32 {
     33     int e=0;  char ch=getchar();
     34     while(ch<'0'||ch>'9')  ch=getchar();
     35     while(ch>='0'&&ch<='9')  {e=(e<<3)+(e<<1)+(ch^48);  ch=getchar();}
     36     return e;
     37 }
     38 int main()
     39 {
     40     T=read();
     41     for(int i=1;i<=T;++i)
     42     {
     43         q[i].n=read();  q[i].m=read();
     44         maxxn=max(maxxn,q[i].n);  maxxm=max(maxxm,q[i].m);
     45     }
     46     for(int i=1;i<=maxxn;++i)//t
     47     {
     48         for(int j=1;j<=maxxm;++j)
     49         {
     50             if(gcd(i,j))  {a[i][j]=1;  g[i][j]=1;}
     51             else  a[i][j]=0;
     52             ls=(a[i-1][j]+a[i][j-1])%mod;
     53             ls=(ls-a[i-1][j-1]+mod)%mod;  ls=(ls+a[i][j])%mod;  a[i][j]=ls;
     54         }
     55     }
     56     for(int o=1;o<=T;++o)
     57     {
     58         ls=(q[o].n*q[o].m)%mod;  ls=(ls*a[q[o].n-1][q[o].m-1])%mod;
     59         q[o].ans=(q[o].ans+ls)%mod;
     60         int i=q[o].n/2,j=q[o].m/2;
     61         ls=(q[o].n*q[o].m)%mod;  ls=(ls*a[i][j])%mod;
     62                 q[o].ans=(q[o].ans-ls+mod)%mod;
     63         q[o].ans=((q[o].ans%mod)+mod)%mod;
     64     }
     65     for(int i=1;i<=maxxn;++i)//b
     66     {
     67         for(int j=1;j<=maxxm;++j)
     68         {
     69             if(g[i][j])  a[i][j]=j;
     70             else  a[i][j]=0;
     71             ls=(a[i-1][j]+a[i][j-1])%mod;
     72             ls=(ls-a[i-1][j-1]+mod)%mod;  ls=(ls+a[i][j])%mod;  a[i][j]=ls;
     73         }
     74     }
     75     for(int o=1;o<=T;++o)
     76     {
     77         ls=(q[o].n*a[q[o].n-1][q[o].m-1])%mod;  q[o].ans=(q[o].ans-ls+mod)%mod;
     78         int i=q[o].n/2,j=q[o].m/2;
     79         ls=(2*q[o].n*a[i][j])%mod;  q[o].ans=(q[o].ans+ls)%mod;
     80         q[o].ans=((q[o].ans%mod)+mod)%mod;
     81     }
     82     for(int i=1;i<=maxxn;++i)//a
     83     {
     84         for(int j=1;j<=maxxm;++j)
     85         {
     86             if(g[i][j])  a[i][j]=i;
     87             else  a[i][j]=0;
     88             ls=(a[i-1][j]+a[i][j-1])%mod;
     89             ls=(ls-a[i-1][j-1]+mod)%mod;  ls=(ls+a[i][j])%mod;  a[i][j]=ls;
     90         }
     91     }
     92     for(int o=1;o<=T;++o)
     93     {
     94         ls=(q[o].m*a[q[o].n-1][q[o].m-1])%mod;  q[o].ans=(q[o].ans-ls+mod)%mod;
     95         int i=q[o].n/2,j=q[o].m/2;
     96         ls=(2*q[o].m*a[i][j])%mod;  q[o].ans=(q[o].ans+ls)%mod;
     97         q[o].ans=((q[o].ans%mod)+mod)%mod;
     98     }
     99     for(int i=1;i<=maxxn;++i)//ab
    100     {
    101         for(int j=1;j<=maxxm;++j)
    102         {
    103             if(g[i][j])  a[i][j]=i*j;
    104             else  a[i][j]=0;
    105             ls=(a[i-1][j]+a[i][j-1])%mod;
    106             ls=(ls-a[i-1][j-1]+mod)%mod;  ls=(ls+a[i][j])%mod;  a[i][j]=ls;
    107         }
    108     }
    109     for(int o=1;o<=T;++o)
    110     {
    111         ls=a[q[o].n-1][q[o].m-1];  q[o].ans=(q[o].ans+ls)%mod;
    112         int i=q[o].n/2,j=q[o].m/2;
    113         ls=(4*a[i][j])%mod;  q[o].ans=(q[o].ans-ls+mod)%mod;
    114         q[o].ans=(q[o].ans*2)%mod;  q[o].ans=(q[o].ans+q[o].n+q[o].m)%mod;
    115         q[o].ans=((q[o].ans%mod)+mod)%mod;
    116         printf("%lld
    ",q[o].ans);
    117     }
    118     return 0;
    119 }    
    View Code

    T2

    这道题有两种解法,一个是点分治,一个是并查集,点分治我显然还没学会,所以就打的并查集的思路

    这题的一个难点在于它既要最小点值,又要最大边值和,那我们考虑枚举最小点值,用并查集直接维护边值和,由于我们是枚举的最小点值,所以只需要让边值和最大,那就并查集记录当前并查集中的最长路径长度,以及这个最长路的两个端点,合并并查集的时候几个端点一通乱配就解决了

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #define maxn 100100
      6 #define int long long
      7 #define ll long long
      8 using namespace std;
      9 struct node{
     10     int val,pos;
     11 }v[maxn];
     12 struct NODE{
     13     ll len;
     14     int po[3];
     15 }bcj[maxn];
     16 int T,n,js;
     17 ll ans;
     18 int head[maxn],to[maxn*2],xia[maxn*2],w[maxn*2];
     19 int deep[maxn],pd[maxn],f[maxn],ww[maxn],bh[maxn],fa[maxn][21];
     20 ll sum[maxn];
     21 bool cmp(const node &a,const node &b)
     22 {
     23     return a.val==b.val?a.pos<b.pos:a.val>b.val;
     24 }
     25 void clear()
     26 {
     27     js=0;  ans=0;
     28     memset(head,0,sizeof(head));  memset(pd,0,sizeof(pd));
     29 }
     30 void add(int x,int y,int z)
     31 {
     32     to[++js]=y;  xia[js]=head[x];  w[js]=z;  head[x]=js;
     33 }
     34 void dfs(int x)
     35 {
     36     pd[x]=1;
     37     for(int i=head[x];i;i=xia[i])
     38     {
     39         int ls=to[i];
     40         if(pd[ls])  continue;
     41         deep[ls]=deep[x]+1;  fa[ls][0]=x;  sum[ls]=sum[x]+w[i];
     42         for(int j=1;j<=20;++j)  fa[ls][j]=fa[fa[ls][j-1]][j-1];
     43         dfs(ls);
     44     }
     45 }
     46 int LCA(int x,int y)
     47 {
     48     if(deep[x]<deep[y])  swap(x,y);
     49     for(int i=20;i>=0;--i)
     50         if(deep[fa[x][i]]>=deep[y])  x=fa[x][i];
     51     if(x==y)  return x;
     52     for(int i=20;i>=0;--i)
     53         if(fa[x][i]!=fa[y][i])  {x=fa[x][i];  y=fa[y][i];}
     54     return fa[x][0];
     55 }
     56 int find(int x)
     57 {
     58     if(f[x]!=x)  f[x]=find(f[x]);
     59     return f[x];
     60 }
     61 void merge(int fa,int son)
     62 {
     63     int po1=0,po2=0;  ll lenn=0;
     64     for(int i=1;i<=2;++i)
     65         for(int j=1;j<=2;++j)
     66         {
     67             int lca=LCA(bcj[fa].po[i],bcj[son].po[j]);
     68             ll lslen=sum[bcj[fa].po[i]]-sum[lca]+sum[bcj[son].po[j]]-sum[lca];
     69             if(lslen>lenn)  {po1=bcj[fa].po[i];  po2=bcj[son].po[j];  lenn=lslen;}
     70         }
     71     if(lenn>bcj[fa].len)  {bcj[fa].len=lenn;  bcj[fa].po[1]=po1;  bcj[fa].po[2]=po2;}
     72     if(bcj[fa].len<bcj[son].len)
     73     {
     74         bcj[fa].len=bcj[son].len;
     75         for(int i=1;i<=2;++i)  bcj[fa].po[i]=bcj[son].po[i];
     76     }
     77 }
     78 main()
     79 {
     80     //freopen("b.in","r",stdin);
     81     scanf("%lld",&T);
     82     while(T--)
     83     {
     84         scanf("%lld",&n);  clear();
     85         for(int i=1;i<=n;++i)  {scanf("%lld",&v[i].val);  v[i].pos=i;  ww[i]=v[i].val;}
     86         for(int i=1;i<n;++i)
     87         {
     88             int u,v,w;  scanf("%lld%lld%lld",&u,&v,&w);
     89             add(u,v,w);  add(v,u,w);
     90         }
     91         deep[1]=1;  sum[1]=0;  dfs(1);  sort(v+1,v+n+1,cmp);
     92         for(int i=1;i<=n;++i)
     93         {
     94             bh[v[i].pos]=i;  f[i]=i;
     95             bcj[i].po[1]=i;  bcj[i].po[2]=i;  bcj[i].len=0;
     96         }
     97         for(int i=1;i<=n;++i)
     98         {
     99             int now=v[i].pos;
    100             for(int j=head[now];j;j=xia[j])
    101             {
    102                 int ls=to[j];
    103                 if(ww[ls]<ww[now]||(ww[ls]==ww[now]&&bh[ls]>i))  continue;
    104                 int ls1=find(f[now]),ls2=find(f[ls]);
    105                 f[ls2]=ls1;  merge(ls1,ls2);
    106             }
    107             ans=max(ans,bcj[now].len*v[i].val);
    108         }
    109         printf("%lld
    ",ans);
    110     }
    111     return 0;
    112 }
    View Code

     T3

    考试的时候觉得有点像好久好久之前考过的旅馆那道题,但是最终还是没打线段树,本来打了一个优先队列优化,但是因为时间不够,没调出来,我就把几十行的代码删了,打了个暴力,正解还是线段树,考虑维护区间最左边花精,最右边花精,最长的空区间长度,以及最长的空区间长度对应的那个中间的点

    对于询问一,直接找1节点对应的答案,也就是$l-1$,$n-r$,$p$先比较长度,长度相同选最靠左的,选过之后把当前位置放上花精,更新线段树

    对于询问二,把该位置清空,更新线段树,$update$那一块细节稍多,yy了好久也没yy明白,最后稍颓了一下下代码。。。。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #define maxn 200200
     6 #define maxx 1001000
     7 #define inf 30000000
     8 using namespace std;
     9 struct node{
    10     int zuo,you,l,r,mid,p;
    11 }a[maxn<<2];
    12 int n,m,opt,num;
    13 int pos[maxx];
    14 inline int read()
    15 {
    16     int e=0;  char ch=getchar();
    17     while(ch<'0'||ch>'9')  ch=getchar();
    18     while(ch>='0'&&ch<='9')  {e=(e<<3)+(e<<1)+(ch^48);  ch=getchar();}
    19     return e;
    20 }
    21 void build(int fa,int l,int r)
    22 {
    23     a[fa].zuo=l;  a[fa].you=r;
    24     if(l==r)  return ;
    25     int mid=(l+r)>>1;
    26     build(2*fa,l,mid);  build(2*fa+1,mid+1,r);
    27 }
    28 void update(int fa)
    29 {
    30     if(a[2*fa].l!=0)  a[fa].l=a[2*fa].l;
    31     else  a[fa].l=a[2*fa+1].l;
    32     if(a[2*fa+1].r!=0)  a[fa].r=a[2*fa+1].r;
    33     else  a[fa].r=a[2*fa].r;
    34     a[fa].mid=a[2*fa].mid;  a[fa].p=a[2*fa].p;
    35     if(a[2*fa].r!=0&&a[2*fa+1].l!=0)
    36     {
    37         int len=(a[2*fa+1].l-a[2*fa].r)>>1;
    38         if(len>a[fa].mid)  {a[fa].mid=len;  a[fa].p=(a[2*fa].r+a[2*fa+1].l)>>1;}
    39         if(a[2*fa+1].mid>a[fa].mid)  {a[fa].mid=a[2*fa+1].mid;  a[fa].p=a[2*fa+1].p;}
    40     }
    41 }
    42 void change(int fa,int x,int op)
    43 {
    44     if(a[fa].zuo==a[fa].you)
    45     {
    46         if(op==1)  {a[fa].l=a[fa].you;  a[fa].r=a[fa].zuo;}
    47         else  {a[fa].l=0;  a[fa].r=0;}
    48         return ;
    49     }
    50     int mid=(a[fa].zuo+a[fa].you)>>1;
    51     if(x<=mid)  change(2*fa,x,op);
    52     else  change(2*fa+1,x,op);
    53     update(fa);
    54 }
    55 int main()
    56 {
    57     n=read();  m=read();
    58     build(1,1,n);
    59     for(int i=1;i<=m;++i)
    60     {
    61         opt=read();  num=read();
    62         if(opt==1)
    63         {
    64             int MA=0,po;
    65             if(a[1].l==0)  {MA=inf;  po=1;}
    66             if(a[1].r==0&&MA!=inf)  {MA=inf;  po=n;}
    67             if(a[1].l-1>MA)  {MA=a[1].l-1;  po=1;}
    68             if(a[1].mid>MA)  {MA=a[1].mid;  po=a[1].p;}
    69             if(n-a[1].r>MA)  {MA=n-a[1].r;  po=n;}
    70             pos[num]=po;  change(1,po,1);
    71             printf("%d
    ",pos[num]);
    72         }
    73         else  change(1,pos[num],0);  pos[num]=0;
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    JavaScript的object和Array引用类型
    JavaScript中JSON的序列化与解析
    JavaScript获取url后面的参数
    JavaScript事件处理程序
    JavaScript手机端页面滑动到底部加载信息(移动端ajax分页)
    666
    jquery的键盘事件
    如何判断是不是微信登录浏览器
    写的挺好 placeholder 的模拟用法
    下雪了还是下冰雹了
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11616706.html
Copyright © 2020-2023  润新知