zoukankan      html  css  js  c++  java
  • 玲珑杯 ACM Round #12

    A

    =w=

    B

    占坑

    C

    题意:有长度为n的序列A和长度为n的序列W,以及一个G,对于Ui,1<=Ui<=Wi,求Σgcd(Ai,Ui)=G的方案数,n<=1e3,Ai<=1e5,Wi<=1e5,G<=1e3

    分析:递推

       f(i,j)表示前i位,当前和为j的方案数

       f(i,j)=Σf(i-1,j-gcd(Ai,k))

       这样直接搞是会TLE

       注意到我们如果对于一个Ai能预处理求出gcd(Ai,k)的所有种类和个数,那么时间就允许了

       考虑Ai、Wi,首先筛出Ai的所有因子,然后use[x]表示gcd为x出现了几次,这个可以根据容斥直接暴力得出

    D

    占坑

    E

    题意:有一个n个节点的树(n<=1e5),每个节点都有颜色,每种颜色最多有20个点。一条可行路径上的点所有颜色都不同,求这样可行路径的条数。

    分析:dfs序+线段树+扫描线

       注意每种颜色最多有20个点

       首先求出dfs序

       那么可以枚举两两相同颜色的点,考虑有多少条路径存在这两个点

       很明显这是一个容斥问题,但这容斥不好求

       有一个很神奇的idea,就是通过dfs序,可以知道这些路径的起点和终点都是dfs序对应的一段区间,可以映射到平面的一块矩形

       那么问题就是求这些矩形的面积并!

       注意这里其实是求点矩阵的并,可以不用乘上两条边的距离,直接按x方向求出当前y方向的有多少个位置点的覆盖数>=1

       至于这个用线段树维护,维护mi[k]和num[k]表示最小值和与最小值相同的位置数量

       注意此题刚开始遍历图要写非递归,不然要爆栈

      1 #include<cstring>
      2 #include<vector>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<stack>
      6 using namespace std;
      7 const int maxn=1e5,inf=1e9;
      8 int n,q,cnt=0,t=0,MAX=0;
      9 int deep[maxn+50],fa[maxn+50][20],head[maxn+50];
     10 int L[maxn+50],R[maxn+50];
     11 int mi[maxn*4+50],lazy[maxn*4+50],num[maxn*4+50];
     12 vector<int> g[maxn+50];
     13 vector<int> color[maxn+50];
     14 stack<int> s;
     15 struct wjmzbmr
     16 {
     17     int y1,y2;
     18 };
     19 vector<wjmzbmr> inc[maxn+50],dec[maxn+50];
     20 void dfs(int k,int last)
     21 {
     22    /* L[k]=++t;
     23     deep[k]=deep[last]+1;
     24     fa[k][0]=last;
     25     for(int i=0;i<g[k].size();++i)
     26         if(g[k][i]!=last) dfs(g[k][i],k);
     27     R[k]=t;*/
     28     while(!s.empty()) s.pop();
     29     memset(head,0,sizeof(head));//head[i]表示第i个点当前遍历到了第几个相邻点
     30     s.push(0);
     31     s.push(1);
     32     while(s.size()>1)
     33     {
     34         int k=s.top();
     35         s.pop();
     36         int last=s.top();
     37         s.push(k);
     38         if(!head[k])
     39         {
     40             L[k]=++t;
     41             deep[k]=deep[last]+1;
     42             fa[k][0]=last;
     43         }
     44         if(head[k]<g[k].size())
     45             if(g[k][head[k]]==last) ++head[k];
     46         if(head[k]==g[k].size())
     47         {
     48             R[k]=t;
     49             s.pop();
     50         }
     51         else
     52             s.push(g[k][head[k]++]);
     53     }
     54 }
     55 int lca(int x,int y)
     56 {
     57     if(deep[x]<deep[y]) swap(x,y);
     58     int d=deep[x]-deep[y];
     59     for(int i=19;i>=0;i--)
     60        if((1<<i)&d) x=fa[x][i];
     61     for(int i=19;i>=0;i--)
     62         if(fa[x][i]!=fa[y][i])
     63         {
     64             x=fa[x][i];
     65             y=fa[y][i];
     66         }
     67     if(x==y)return x;else return fa[x][0];
     68 }
     69 int low(int u,int v)
     70 {
     71     int d=deep[v]-deep[u]-1;
     72     for(int i=19;i>=0;i--)
     73        if((1<<i)&d) v=fa[v][i];
     74     return v;
     75 }
     76 void insert(int x1,int x2,int y1,int y2)
     77 {
     78     if(x1>x2||y1>y2) return;
     79     //printf("%d %d %d %d
    ",x1,x2,y1,y2);
     80     inc[x1].push_back({y1,y2});
     81     dec[x2+1].push_back({y1,y2});
     82 }
     83 void build(int k,int l,int r)
     84 {
     85     if(l>r) return;
     86     if(l==r)
     87     {
     88         num[k]=1;
     89         return;
     90     }
     91     num[k]=r-l+1;
     92     int mid=(l+r)>>1;
     93     build(k+k,l,mid);
     94     build(k+k+1,mid+1,r);
     95 }
     96 void pushdown(int k)
     97 {
     98     int l=k+k,r=k+k+1;
     99     lazy[l]+=lazy[k],mi[l]+=lazy[k];
    100     lazy[r]+=lazy[k],mi[r]+=lazy[k];
    101     lazy[k]=0;
    102 }
    103 void update(int k)
    104 {
    105     int l=k+k,r=k+k+1;
    106     mi[k]=min(mi[r],mi[l]);
    107     num[k]=0;
    108     if(mi[l]==mi[k]) num[k]+=num[l];
    109     if(mi[r]==mi[k]) num[k]+=num[r];
    110 }
    111 void add(int k,int l,int r,int x,int y,int num)
    112 {
    113     if(l>r||r<x||l>y) return;
    114     if(x<=l&&r<=y)
    115     {
    116         lazy[k]+=num;
    117         mi[k]+=num;
    118         return;
    119     }
    120     if(l==r) return;
    121     int mid=(l+r)>>1;
    122     pushdown(k);
    123     add(k+k,l,mid,x,y,num);
    124     add(k+k+1,mid+1,r,x,y,num);
    125     update(k);
    126 }
    127 int query()
    128 {
    129     if(mi[1]) return 0;else return num[1];
    130 }
    131 int main()
    132 {
    133     /*int size = 256 << 20; // 256MB
    134     char *p = (char*)malloc(size) + size;
    135     __asm__("movl %0, %%esp
    " :: "r"(p));*/
    136     freopen("ce.in","r",stdin);
    137     //freopen("ce.out","w",stdout);
    138     scanf("%d",&n);
    139    // printf("ok");
    140     for(int i=1;i<n;i++)
    141     {
    142         int u,v;
    143         scanf("%d%d",&u,&v);
    144         g[u].push_back(v);
    145         g[v].push_back(u);
    146     }
    147     for(int i=1;i<=n;++i)
    148     {
    149         int x;
    150         scanf("%d",&x);
    151         color[x].push_back(i);
    152         cnt=max(cnt,x);
    153     }
    154     dfs(1,0);
    155     for(int k=1;k<=19;++k)
    156         for(int i=1;i<=n;++i)
    157             fa[i][k]=fa[fa[i][k-1]][k-1];
    158     for(int c=1;c<=cnt;++c)
    159     {
    160         for(int i=0;i<color[c].size();++i)
    161             for(int j=i+1;j<color[c].size();++j)
    162             {
    163                 int u=color[c][i],v=color[c][j];
    164                 if(deep[u]>deep[v]) swap(u,v);
    165                 if(lca(u,v)!=u) insert(L[u],R[u],L[v],R[v]),insert(L[v],R[v],L[u],R[u]);
    166                 else
    167                 {
    168                     int x=low(u,v);
    169                     insert(1,L[x]-1,L[v],R[v]);
    170                     insert(R[x]+1,n,L[v],R[v]);
    171                     insert(L[v],R[v],1,L[x]-1);
    172                     insert(L[v],R[v],R[x]+1,n);
    173                 }
    174             }
    175     }
    176     build(1,1,n);
    177     long long ans=0;
    178     for(int i=1;i<=n;++i)
    179     {
    180         for(int j=0;j<inc[i].size();++j) add(1,1,n,inc[i][j].y1,inc[i][j].y2,1);
    181         for(int j=0;j<dec[i].size();++j) add(1,1,n,dec[i][j].y1,dec[i][j].y2,-1);
    182         ans+=1LL*query();
    183     }
    184     printf("%lld
    ",(ans-n)/2);
    185     return 0;
    186 }
    View Code
  • 相关阅读:
    Caffe + Ubuntu 15.04 + CUDA 7.0 新手安装配置指南
    姚斌分布式作业一
    一个简单正则表达式引擎的实现
    学习编程的方法
    [Leetcode]012. Integer to Roman
    [Leetcode]011. Container With Most Water
    JOS lab1 part2 分析
    我的Android Studio配置
    [Leetcode]009.Palindrome Number
    [Leetcode]008.String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/wmrv587/p/6597103.html
Copyright © 2011-2022 走看看