Wannafly模拟赛4
2017-10-14 04:08
253 查看
A Treepath
给定一棵n个点的树,问其中有多少条长度为偶数的路径。路径的长度为经过的边的条数。x到y与y到x被视为同一条路径。路径的起点与终点不能相同。#include<bits/stdc++.h> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,0x3f,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define MEMx(a,b) memset(a,b,sizeof(a)); #define INF (0x3f3f3f3f) #define F (1000000007) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) #define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans); #define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a <<endl; #define PRi2D(a,n,m) For(i,n) { \ For(j,m-1) cout<<a[i][j]<<' ';\ cout<<a[i][m]<<endl; \ } #pragma comment(linker, "/STACK:102400000,102400000") #define ALL(x) (x).begin(),(x).end() #define gmax(a,b) a=max(a,b); #define gmin(a,b) a=min(a,b); typedef long long ll; typedef long double ld; typedef unsigned long long ull; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return ((a-b)%F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (101000) vi e[MAXN]; ll ans=0; int j[MAXN]={},o[MAXN]={}; void dfs(int x,int fa) { o[x]=1;j[x]=0; for(auto v:e[x]) { if (v!=fa) { dfs(v,x); o[x]+=j[v]; j[x]+=o[v]; ans+=o[x]*j[v]; ans+=o[v]*j[x]; } } } int main() { // freopen("A.in","r",stdin); // freopen(".out","w",stdout); int n=read(); For(i,n-1) { int u=read(),v=read(); e[u].pb(v);e[v].pb(u); } dfs(1,0); cout<<ans<<endl; return 0; }
B Xorto
给定一个长度为n的整数数组,问有多少对互不重叠的非空区间,使得两个区间内的数的异或和为0。#include<bits/stdc++.h> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,0x3f,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define MEMx(a,b) memset(a,b,sizeof(a)); #define INF (0x3f3f3f3f) #define F (1000000007) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) #define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans); #define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a <<endl; #define PRi2D(a,n,m) For(i,n) { \ For(j,m-1) cout<<a[i][j]<<' ';\ cout<<a[i][m]<<endl; \ } #pragma comment(linker, "/STACK:102400000,102400000") #define ALL(x) (x).begin(),(x).end() #define gmax(a,b) a=max(a,b); #define gmin(a,b) a=min(a,b); typedef long long ll; typedef long double ld; typedef unsigned long long ull; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return ((a-b)%F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (1010000) ll a[MAXN]; ll cnt[MAXN]; ll h[MAXN],h2[MAXN]; int main() { freopen("B.in","r",stdin); // freopen(".out","w",stdout); int n=read(); For(i,n) { a[i]=read(); } ll s=0,p=0; MEM(cnt) cnt[s]++; For(i,n) { s^=a[i]; p+=cnt[s]; cnt[s]++; h[i]=p; } s=0,p=0; MEM(cnt) cnt[s]++; ll ans=0; ForD(i,n) { s^=a[i]; p+=cnt[s]; ans += cnt[s] * h[i-1]; cnt[s]++; h2[i]=p; } cout<<ans<<endl; return 0; }
C MMSet2
给定一棵n个节点的树,点编号为1…n。Q次询问,每次询问给定一个点集S,令fu=maxv⊂S(dis(u,v))
你需要求出minu=1⋯n(fu)。
其中dist(u,v)表示树上路径(u,v)的边数。
答案是虚树直径除2,向上取整。
注意如果只有一个点,答案是0。
#include<iostream> #include<set> #include<map> #include<cstdio> #include<cstring> #include<cstdlib> #include<ctime> #include<vector> #include<queue> #include<algorithm> #include<cmath> #define inf 2000000000 #define pa pair<int,int> #define ll long long using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll tot; int bin[20]; int n,K,top,cnt,q,ind,ans1,ans2; int last[1000005],last2[1000005],v[1000005]; int mx[1000005],mn[1000005]; int fa[1000005][20],deep[1000005],mark[1000005],st[1000005],h[1000005]; ll size[1000005],f[1000005]; struct edge{ int to,next,v; }e[2000005],ed[2000005]; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } void insert2(int u,int v) { if(u==v)return; ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt;ed[cnt].v=deep[v]-deep[u]; } void pre(int x) { mark[x]=++ind; for(int i=1;bin[i]<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=last[x];i;i=e[i].next) if(e[i].to!=fa[x][0]) { deep[e[i].to]=deep[x]+1; fa[e[i].to][0]=x; pre(e[i].to); } } int lca(int x,int y) { if(deep[x]<deep[y])swap(x,y); int t=deep[x]-deep[y]; for(int i=0;bin[i]<=t;i++) if(bin[i]&t)x=fa[x][i]; for(int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if(x==y)return x; return fa[x][0]; } bool cmp(int a,int b) { return mark[a]<mark[b]; } void dp(int x) { int tmp=0; size[x]=v[x];f[x]=0; mn[x]=v[x]?0:inf; mx[x]=v[x]?0:-inf; for(int i=last2[x];i;i=ed[i].next) { int y=ed[i].to; dp(y); tot+=(f[x]+size[x]*ed[i].v)*size[y]+f[y]*size[x]; size[x]+=size[y]; f[x]+=f[y]+ed[i].v*size[y]; ans1=min(ans1,mn[x]+mn[y]+ed[i].v); ans2=max(ans2,mx[x]+mx[y]+ed[i].v); mn[x]=min(mn[x],mn[y]+ed[i].v); mx[x]=max(mx[x],mx[y]+ed[i].v); } last2[x]=0; } void solve() { K=read(); for(int i=1;i<=K;i++)h[i]=read(); for(int i=1;i<=K;i++)v[h[i]]=1; sort(h+1,h+K+1,cmp); top=cnt=0; int x,f; st[++top]=1; for(int i=1;i<=K;i++) { x=h[i];f=lca(x,st[top]); if(f==st[top]){st[++top]=x;continue;} while(f==lca(x,st[top-1])) { insert2(st[top-1],st[top]); top--;f=lca(x,st[top]); } insert2(f,st[top]); st[top]=f;st[++top]=x; } while(--top)insert2(st[top],st[top+1]); ans1=inf;ans2=-inf;tot=0; dp(1); if (K==1) puts("0"); else printf("%d\n",ans2-ans2/2); for(int i=1;i<=K;i++)v[h[i]]=0; } int main() { // freopen("c.in","r",stdin); // freopen(".out","w",stdout); bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1; n=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); insert(u,v); } pre(1); q=read(); while(q--)solve(); return 0; }
D Color
给一个没有重边的二分图, 要求给边染色. 有公共点的边不能同色. 问最少用多少种颜色, 并任意构造一组方案. (0E Cut
给定一个无向简单图(即无重边无自环). 每条边都有一个权值. 这个图的一个鸽, 指的是将它的点集划分为两个不重不漏的集合S和T. 这个鸽的权值, 是所有两个端点分别属于S和T的边的权值的异或和(即, S内部的边和T内部的边都不算). 现在问这个图的鸽的所有可能权值的和是多少. 由于这个数很大, 只需要输出前9位, 不足9位则全部输出.相关文章推荐
- Wannafly模拟赛2 A题
- Wannafly模拟赛4 B.Distance 最大曼哈顿距离
- Wannafly模拟赛4 A Laptop (前缀数组)
- Wannafly模拟赛4:A -Laptop(后缀)
- 10.9wannafly模拟赛
- Wannafly模拟赛4 B.Distance 最大曼哈顿距离
- Wannafly模拟赛4-C-sum(二进制拆分+树状数组)
- Wannafly模拟赛5 A Split
- 牛客网 Wannafly模拟赛2 树 dp+思维
- Wannafly模拟赛2 B river(拉格朗日乘数法)
- Wannafly模拟赛3 绝对半径2051(尺取)
- Wannafly模拟赛4 B Distance(枚举 最大曼哈顿距离模板)
- Wannafly模拟赛4 B Distance
- Wannafly模拟赛5 D Aria(全排列)
- Wannafly模拟赛4 题解
- Wannafly模拟赛 矩阵 [矩阵hash+二分]
- Wannafly模拟赛3 E 绝对半径2051【尺取】(可做模板)
- Wannafly模拟赛4 A Laptop (RMQ)
- Wannafly模拟赛5 A Split 【贪心】
- Wannafly模拟赛3 反蝴蝶效应