2016大连网络赛
Posted As3asddd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016大连网络赛相关的知识,希望对你有一定的参考价值。
1010 Weak Pair
题解:树状数组/线段树 +离散化+dfs 对于每个a[i],将k/a[i]也放进去离散,这样的话对于每个数就能知道k/a[i]之前的有多少个数,从根节点开始dfs,然后找向它的子节点,看能不能匹配,而会造成影响的只有兄弟节点,那么在每次访问完一个节点的子节点之后删除这个点的贡献
线段树版本:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <stdlib.h> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <string> 10 using namespace std; 11 const int maxn=3*1e5+10; 12 #define MS(a,b) memset(a,b,sizeof(a)) 13 long long a[maxn]; 14 long long b[maxn]; 15 long long k; 16 int n,m; 17 vector<int> G[maxn]; 18 int in[maxn]; 19 long long ans; 20 struct node 21 { 22 int l,r; 23 int mid(){return (l+r)>>1;} 24 long long sum; 25 }; 26 node tree[maxn<<2]; 27 void pushup(int rt) 28 { 29 tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; 30 } 31 void build(int l,int r,int rt) 32 { 33 tree[rt].l=l,tree[rt].r=r; 34 tree[rt].sum=0; 35 if(l==r) return ; 36 int mid=tree[rt].mid(); 37 build(l,mid,rt<<1); 38 build(mid+1,r,rt<<1|1); 39 } 40 void update(int index,int x,int L,int R,int rt) 41 { 42 if(L==index&&R==index) 43 { 44 tree[rt].sum+=x; 45 return ; 46 } 47 int mid=tree[rt].mid(); 48 if(index<=mid) update(index,x,L,mid,rt<<1); 49 else if(index>mid) update(index,x,mid+1,R,rt<<1|1); 50 pushup(rt); 51 } 52 long long query(int l,int r,int L,int R,int rt) 53 { 54 if(L>=l&&R<=r) return tree[rt].sum; 55 int mid=tree[rt].mid(); 56 long long ans=0; 57 if(l<=mid) ans+=query(l,r,L,mid,rt<<1); 58 if(r>mid) ans+=query(l,r,mid+1,R,rt<<1|1); 59 return ans; 60 } 61 void dfs(int x) 62 { 63 int l=lower_bound(b+1,b+1+m,k/a[x])-b; 64 int pos=lower_bound(b+1,b+1+m,a[x])-b; 65 ans+=query(1,l,1,m,1); 66 update(pos,1,1,m,1); 67 for(int i=0;i<G[x].size();i++) dfs(G[x][i]); 68 update(pos,-1,1,m,1); 69 } 70 void init() 71 { 72 for(int i=0;i<=n+1;i++) G[i].clear(); 73 build(1,m,1); 74 MS(in,0); 75 ans=0; 76 } 77 int main() 78 { 79 int T; 80 scanf("%d",&T); 81 while(T--) 82 { 83 //init(); 84 scanf("%d %lld",&n,&k); 85 int cnt=1; 86 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 87 for(int i=1;i<=n;i++) 88 { 89 b[cnt]=a[i]; 90 cnt++; 91 b[cnt]=k/a[i]; 92 cnt++; 93 } 94 m=cnt-1; 95 sort(b+1,b+1+m); 96 init(); 97 for(int i=1;i<=n-1;i++) 98 { 99 int x,y; 100 scanf("%d %d",&x,&y); 101 G[x].push_back(y); 102 in[y]++; 103 } 104 int root; 105 for(int i=1;i<=n;i++) 106 { 107 if(in[i]==0) 108 { 109 root=i; 110 break; 111 } 112 } 113 dfs(root); 114 printf("%lld\\n",ans); 115 116 } 117 return 0; 118 }
树状数组版本:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #include <vector> #include <queue> #include <stack> #include <string> using namespace std; const int maxn=3*1e5+10; #define MS(a,b) memset(a,b,sizeof(a)) long long a[maxn]; long long b[maxn]; long long k; int n,m; vector<int> G[maxn]; int in[maxn]; long long ans; long long tree[maxn]; void add(int pos,int x) { while(pos<=2*m) { tree[pos]+=x; pos+=(pos&(-pos)); } } long long query(int pos) { long long sum=0; while(pos>0) { sum+=tree[pos]; pos-=(pos&(-pos)); } return sum; } void dfs(int x) { int l=lower_bound(b+1,b+1+m,k/a[x])-b; int pos=lower_bound(b+1,b+1+m,a[x])-b; ans+=query(l); add(pos,1); for(int i=0;i<G[x].size();i++) dfs(G[x][i]); add(pos,-1); } void init() { for(int i=0;i<=n+1;i++) G[i].clear(); MS(tree,0); MS(in,0); ans=0; } int main() { int T; scanf("%d",&T); while(T--) { init(); scanf("%d %lld",&n,&k); int cnt=1; for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<=n;i++) { b[cnt]=a[i]; cnt++; b[cnt]=k/a[i]; cnt++; } m=cnt-1; sort(b+1,b+1+m); for(int i=1;i<=n-1;i++) { int x,y; scanf("%d %d",&x,&y); G[x].push_back(y); in[y]++; } int root; for(int i=1;i<=n;i++) { if(in[i]==0) { root=i; break; } } dfs(root); printf("%lld\\n",ans); } return 0; }
1009 Sparse Graph
题解:就是求一个补图的最短路,考虑到实际上补图每条边的权值时一样的,那么可以使用bfs求一个最短路,用set保存访问过的点和没访问过的点,因为点如果访问过了,那么肯定肯定是最短的,再从已经访问到的点开始扩展,做完这题可以看看scu4444和这题的思路基本一样
1 #include <iostream> 2 #include <algorithm> 3 #include <queue> 4 #include <set> 5 #include <stdio.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include <map> 9 #include <vector> 10 #include <math.h> 11 using namespace std; 12 const int maxn=200*1000+10; 13 int n,m; 14 set<int> novis; 15 set<int> vis; 16 vector<int> G[maxn]; 17 int dis[maxn]; 18 void bfs(int s) 19 { 20 memset(dis,-1,sizeof(dis)); 21 queue<int> q; 22 q.push(s); 23 dis[s]=0; 24 while(!q.empty()&&novis.size()) 25 { 26 int x=q.front(); 27 q.pop(); 28 for(int i=0;i<G[x].size();i++) 29 { 30 if(!novis.count(G[x][i])) continue; 31 novis.erase(G[x][i]); 32 vis.insert(G[x][i]); 33 } 34 for(auto it:novis) 35 { 36 dis[it]=dis[x]+1; 37 q.push(it); 38 } 39 novis.swap(vis); 40 vis.clear(); 41 42 } 43 } 44 int main() 45 { 46 int T; 47 scanf("%d",&T); 48 while(T--) 49 { 50 vis.clear(); 51 novis.clear(); 52 scanf("%d %d",&n,&m); 53 for(int i=1;i<=n;i++) G[i].clear(); 54 for(int i=1;i<=m;i++) 55 { 56 int x,y; 57 scanf("%d %d",&x,&y); 58 G[x].push_back(y); 59 G[y].push_back(x); 60 } 61 int s; 62 scanf("%d",&s); 63 for(int i=1;i<=n;i++) 64 { 65 if(i==s) continue; 66 novis.insert(i); 67 } 68 int cnt=1; 69 bfs(s); 70 for(int i=1;i<=n;i++) 71 { 72 if(i==s) continue; 73 cnt++; 74 printf("%d%c",dis[i],cnt==n?\'\\n\':\' \'); 75 76 } 77 78 } 79 return 0; 80 }
1008 Function
题解:如果a>=b,那么a%b<=a/2;
一个数n从本来的位置递减到0最多只需要logn次,也就是往右递减的位置最多不超过30个,那么我们就可以预处理出每个数往右递减的位置,然后离线询问,
用一个优先队列存储数和数所在的位置,比如8 7 6 9 10,先push(8,1)进去,然后每次把队首拿出来,8%7=1,把(1,1)push进去,然后把(8,1)pop出来,(7,2)push进去,优先队列最大值优先,当队首元素小于当前元素的时候,把当前元素和位置push进去,开始枚举下一个数
1 #include <iostream> 2 #include <algorithm> 3 #include <stdio.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <queue> 7 using namespace std; 8 const int maxn=1e5+10; 9 struct node 10 { 11 int id; 12 int data; 13 int cnt; 14 friend bool operator < (const node&a,const node&b) 15 { 16 return a.data<b.data; 17 } 18 }; 19 struct node2 20 { 21 int pos; 22 int data; 23 void init() 24 { 25 pos=0; 26 } 27 }; 28 node a[maxn]; 29 node2 pos[maxn][32]; 30 priority_queue<node> q; 31 int main() 32 { 33 int T; 34 scanf("%d",&T); 35 while(T--) 36 { 37 while(!q.empty()) q.pop(); 38 int n; 39 scanf("%d",&n); 40 for(int i=1;i<=n;i++) 41 { 42 int x; 43 scanf("%d",&x); 44 a[i].data=x; 45 a[i].id=i; 46 a[i].cnt=0; 47 pos[i][0].data=x; 48 pos[i][0].pos=i; 49 for(int j=1;j<=30;j++) 50 { 51 pos[i][j].init(); 52 } 53 } 54 q.push(a[1]); 55 for(int i=2;i<=n;i++) 56 { 57 node tmp; 58 while(q.top().data>=a[i].data) 59 { 60 tmp=q.top(); 61 q.pop(); 62 tmp.data%=a[i].data; 63 tmp.cnt+=1; 64 pos[tmp.id][tmp.cnt].pos=i; 65 pos[tmp.id][tmp.cnt].data=tmp.data; 66 q.push(tmp); 67 68 } 69 q.push(a[i]); 70 } 71 int m; 72 scanf("%d",&m); 73 while(m--) 74 { 75 int l,r; 76 int ans; 77 scanf("%d %d",&l,&r); 78 if(l==r){ 79 printf("%d\\n",a[l].data); 80 continue; 81 } 82 else 83 { 84 for(int i=0;i<=30;i++) 85 { 86 87 if(pos[l][i].pos>r||pos[l][i].pos==0) break; 88 ans=pos[l][i].data; 89 } 90 printf("%d\\n",ans); 91 } 92 } 93 94 } 95 return 0; 96 }
1006 Football Games
题解:迷幻的题目。。。
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <algorithm> 6 #include <vector> 7 #include <map> 8 #include <queue> 9 using namespace std; 10 const int maxn=1e5; 11 int b[maxn]; 12 int main() 13 { 14 int n,m; 15 while(scanf("%d",&m)!=EOF) 16 { 17 while(m--) 18 { 19 scanf("%d",&2016大连网络赛 Football Games2016大连网络赛 Different GCD Subarray Query