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 }