A BPM136
对于两边取对数,然后将pi和pj除过去,就可以DP了
方程为f[i]=sum{f[j]}+1 if ln
(a[j])/j < ln
(a[i])/i
1 /* *********************************************** 2 Author :BPM136 3 Created Time :2018/7/7 19:11:25 4 File Name :A.cpp 5 ************************************************ */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstdlib> 11 #include<cmath> 12 #include<cstring> 13 #include<vector> 14 using namespace std; 15 16 const int N = 105; 17 18 long long f[N]; 19 int n; 20 int a[N]; 21 22 int main() { 23 long long ans=0; 24 cin>>n; 25 for(int i=1;i<=n;i++) cin>>a[i]; 26 for(int i=1;i<=n;i++) { 27 f[i]=1; 28 for(int j=1;j<i;j++) if(log(a[j]*1.0)/j < log(a[i]*1.0)/i) f[i]+=f[j]; 29 ans+=f[i]; 30 } 31 cout<<ans<<endl; 32 return 0; 33 }
B BPM136
给定M条有向边,询问是否有环,输入假加密(因为答案一定前面都是1后面都是0)
因为是假加密,所以可以二分答案,dfs判定即可
1 /* *********************************************** 2 Author :BPM136 3 Created Time :2018/7/7 19:36:40 4 File Name :B.cpp 5 ************************************************ */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstdlib> 11 #include<cmath> 12 #include<cstring> 13 #include<vector> 14 using namespace std; 15 16 const int N = 200005; 17 18 struct edge { 19 int y,next; 20 }e[N<<1],_e[N<<1]; 21 int last[N],ne; 22 int _last[N],_ne; 23 24 struct node { 25 int x,y; 26 }a[N]; 27 28 int n,m; 29 30 void add(int x,int y) { 31 e[++ne].y=y; e[ne].next=last[x]; last[x]=ne; 32 _e[++_ne].y=x; _e[_ne].next=_last[y]; _last[y]=_ne; 33 } 34 35 int lfcou=0; 36 int sortrem[N]; 37 int sortcou; 38 39 int vis1[N]; 40 int vis2[N]; 41 42 void dfs1(int x) { 43 vis1[x]=1; 44 for(int i=last[x];i!=0;i=e[i].next) if(vis1[e[i].y]==0) { 45 dfs1(e[i].y); 46 } 47 sortrem[sortcou++]=x; 48 } 49 50 void dfs2(int x) { 51 vis2[x]=1; 52 for(int i=_last[x];i!=0;i=_e[i].next) if(!vis2[_e[i].y]) { 53 dfs2(_e[i].y); 54 } 55 } 56 57 int check(int LIM) { 58 memset(last,0,sizeof(last)); 59 memset(_last,0,sizeof(_last)); 60 _ne=0; 61 ne=0; 62 int ans=0; 63 for(int i=1;i<=LIM;i++) { 64 int x=a[i].x; 65 int y=a[i].y; 66 x=x-1-ans; y=y-1-ans; 67 x=(x+n)%n; 68 y=(y+n)%n; 69 if(x==0) x=n; 70 if(y==0) y=n; 71 72 ans=1; 73 add(x,y); 74 } 75 memset(vis1,0,sizeof(vis1)); 76 memset(vis2,0,sizeof(vis2)); 77 memset(sortrem,0,sizeof(sortrem)); 78 lfcou=0; 79 sortcou=0; 80 for(int i=1;i<=n;i++) if(vis1[i]==0) { 81 dfs1(i); 82 } 83 for(int i=sortcou-1;i>=0;i--) if(vis2[sortrem[i]]==0) { 84 ++lfcou; 85 dfs2(sortrem[i]); 86 } 87 if(lfcou==n) return 1; 88 return 0; 89 } 90 91 int main() { 92 scanf("%d%d",&n,&m); 93 for(int i=1;i<=m;i++) { 94 int x,y; 95 scanf("%d%d",&x,&y); 96 a[i].x=x; 97 a[i].y=y; 98 } 99 100 int l=1,r=m; 101 int ans=-1; 102 while(l<=r) { 103 int mid=(l+r)/2; 104 if(check(mid)) { 105 l=mid+1; 106 ans=mid; 107 } else r=mid-1; 108 } 109 for(int i=1;i<=ans;i++) puts("1"); 110 for(int i=ans+1;i<=m;i++) puts("0"); 111 return 0; 112 }
C BPM136
给了张无向图,一些边上面有0和1,另一些为-1,其中-1的边可以定为0或者1,要求这张图每一个环的异或和为0,问方案数
考虑先加入01边,如果合法,再慢慢加入-1边,加入-1边时,如果这条边在一个连通块内,那么权值直接定下来了,否则就有两种选法。
注意dfs判断合法的时候continue和return应该写哪个
1 /* *********************************************** 2 Author :BPM136 3 Created Time :2018/7/7 21:34:50 4 File Name :C.cpp 5 ************************************************ */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstdlib> 11 #include<cmath> 12 #include<cstring> 13 #include<vector> 14 using namespace std; 15 16 const int N = 100005; 17 const long long MOD = 998244353; 18 19 struct edge { 20 int x,y,z; 21 int next; 22 }e[N<<1],b[N<<1]; 23 int last[N],ne=0; 24 25 int n,m; 26 27 void add(int x,int y,int z) { 28 e[++ne].y=y; e[ne].z=z; e[ne].next=last[x]; last[x]=ne; 29 } 30 void add2(int x,int y,int z) { 31 add(x,y,z); 32 add(y,x,z); 33 } 34 35 bool cmp_edge(edge a,edge b) { 36 return a.z>b.z; 37 } 38 39 int xo[N]; 40 int vis[N]; 41 int flag=0; 42 void dfs(int x,int pre) { 43 vis[x]=1; 44 for(int i=last[x];i!=0;i=e[i].next) if(e[i].y!=pre) { 45 if(vis[e[i].y]) { 46 if(xo[e[i].y]^xo[x]^e[i].z == 1) flag=1; 47 continue; 48 } 49 xo[e[i].y]=xo[x]^e[i].z; 50 dfs(e[i].y,x); 51 } 52 } 53 54 int F_f[N]; 55 int F_find(int x) { 56 if(F_f[x]==x) return x; 57 return F_f[x]=F_find(F_f[x]); 58 } 59 60 int main() { 61 scanf("%d%d",&n,&m); 62 for(int i=1;i<=m;i++) { 63 int x,y,z; 64 scanf("%d%d%d",&x,&y,&z); 65 b[i].x=x; 66 b[i].y=y; 67 b[i].z=z; 68 } 69 //sort(b+1,b+m+1,cmp_edge); 70 for(int i=1;i<=n;i++) F_f[i]=i; 71 for(int i=1;i<=m;i++) { 72 if(b[i].z==-1) continue; 73 74 int x=b[i].x; 75 int y=b[i].y; 76 int z=b[i].z; 77 add2(x,y,z); 78 int dx=F_find(x); 79 int dy=F_find(y); 80 if(dx!=dy) F_f[dx]=dy; 81 } 82 for(int i=1;i<=n;i++) if(vis[i]==0) { 83 dfs(i,0); 84 } 85 if(flag==1) { 86 puts("0"); 87 return 0; 88 } 89 90 long long ans=1; 91 for(int i=1;i<=m;i++) if(b[i].z==-1) { 92 int dx=F_find(b[i].x); 93 int dy=F_find(b[i].y); 94 if(dx!=dy) { 95 ans=ans * 2 % MOD; 96 F_f[dx]=dy; 97 } 98 } 99 cout<<ans; 100 return 0; 101 }
D BPM136
因为b序列的下凸性很容易可知b一定取a的下凸壳,上下平移一下即可,答案一定在下凸壳和ai的最大差的一半处取到。
注意long long
1 /* *********************************************** 2 Author :BPM136 3 Created Time :2018/7/14 12:03:17 4 File Name :D.cpp 5 ************************************************ */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstdlib> 11 #include<cmath> 12 #include<cstring> 13 #include<vector> 14 using namespace std; 15 16 const int N = 1000005; 17 18 struct point { 19 long long x,y; 20 point() {} 21 point(int _x,int _y) : x(_x),y(_y) {} 22 point operator-(const point &b) { 23 point ret; 24 ret.x=x-b.x; 25 ret.y=y-b.y; 26 return ret; 27 } 28 }; 29 30 int a[N]; 31 int n; 32 int sta[N]; 33 int m; 34 35 long long cross(point a,point b) { 36 return a.x*b.y-a.y*b.x; 37 } 38 long long cross(point a,point b,point c) { 39 return cross(b-a,c-a); 40 } 41 long long cross(int x,int y,int z) { 42 return (long long)(y-x)*(a[z]-a[x])-(long long)(z-x)*(a[y]-a[x]); 43 } 44 45 long long GCD(long long a,long long b) { 46 if(b==0) return a; 47 return GCD(b,a%b); 48 } 49 50 void f_update(long long &fz,long long &fm,long long x,long long y) { 51 y<<=1; 52 long long gcd=GCD(x,y); 53 x/=gcd; 54 y/=gcd; 55 if(y*fz<x*fm) fz=x,fm=y; 56 } 57 58 int main() { 59 scanf("%d",&n); 60 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 61 m=0; 62 for(int i=1;i<=n;i++) { 63 //while(m>=2 && cross( point(sta[m-1],a[ sta[m-1] ]) , point(sta[m],a[ sta[m] ]) , point(i,a[i]) )<=0 ) m--; 64 while(m>=2 && cross(sta[m-1],sta[m],i)<0) m--; 65 sta[++m]=i; 66 } 67 //cout<<"tubao : "<<m<<endl; 68 //for(int i=1;i<=m;i++) cout<<sta[i]<<' '; cout<<endl; 69 long long fz=0,fm=1; 70 for(int i=1,R=1;i<=n;i++) { 71 while(R<=m && sta[R]<i) R++; 72 if(sta[R]==i) continue; 73 long long tfz,tfm; 74 long long lenx=sta[R]-sta[R-1]; 75 long long leny=a[sta[R]]-a[sta[R-1]]; 76 long long deltax=i-sta[R-1]; 77 long long deltay=a[i]-a[sta[R-1]]; 78 tfz=lenx*deltay-deltax*leny; 79 tfm=lenx; 80 f_update(fz,fm,tfz,tfm); 81 } 82 if(fm==1) cout<<fz<<endl; else cout<<fz<<'/'<<fm<<endl; 83 return 0; 84 }
E BPM136
给定一棵树,显然指定一些路径,所有通过这些路径的商队将会消失,每一对有序点对都会有一只商队,问最后剩下多少商队
考虑dfs序,那么每一条指定的路径相当于在一个正方形里面切掉两个矩形,而后二维数点即可(线段树+扫描线)
1 /* *********************************************** 2 Author :BPM136 3 Created Time :2018/7/7 20:47:52 4 File Name :E_m.cpp 5 ************************************************ */ 6 7 #include<iostream> 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstdlib> 11 #include<cmath> 12 #include<cstring> 13 #include<vector> 14 using namespace std; 15 16 const int N = 100005; 17 18 struct edge { 19 int y,next; 20 }e[N<<1]; 21 int last[N],ne=0; 22 23 void add(int x,int y) { 24 e[++ne].y=y; e[ne].next=last[x]; last[x]=ne; 25 } 26 void add2(int x,int y) { 27 add(x,y); 28 add(y,x); 29 } 30 31 int dfn[N],en[N],tim=0; 32 int dep[N]; 33 34 int fa[N][21]; 35 36 struct node { 37 int x,y; 38 node() {} 39 node(int _x,int _y) : x(_x),y(_y) {} 40 }; 41 vector< node > vec1[N]; 42 vector< node > vec2[N]; 43 44 void vec_add(int x1,int x2,int y1,int y2) { 45 vec1[x1].push_back(node(y1,y2)); 46 vec1[y1].push_back(node(x1,x2)); 47 48 vec2[x2+1].push_back(node(y1,y2)); 49 vec2[y2+1].push_back(node(x1,x2)); 50 } 51 52 int n,m; 53 54 void dfs(int x,int pre) { 55 dfn[x]=++tim; 56 dep[x]=dep[pre]+1; 57 58 fa[x][0]=pre; 59 for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; 60 for(int i=last[x];i!=0;i=e[i].next) if(e[i].y!=pre) { 61 dfs(e[i].y,x); 62 } 63 en[x]=tim; 64 } 65 66 namespace seg { 67 #define LSON (k<<1) 68 #define RSON (k<<1|1) 69 #define MID ((l+r)/2) 70 71 long long sum[N<<4]; 72 int lz[N<<4]; 73 74 void pushup(int k,int l,int r) { 75 if(lz[k]) { 76 sum[k]=r-l+1; 77 return ; 78 } 79 if(l==r) { 80 sum[k]=0; 81 return ; 82 } 83 sum[k]=sum[LSON]+sum[RSON]; 84 } 85 86 void add(int k,int l,int r,int ll,int rr,int val) { 87 if(l==ll && r==rr) { 88 lz[k]+=val; 89 pushup(k,l,r); 90 return ; 91 } 92 int mid=MID; 93 if(rr<=mid) add(LSON,l,mid,ll,rr,val); 94 else if(ll>mid) add(RSON,mid+1,r,ll,rr,val); 95 else { 96 add(LSON,l,mid,ll,mid,val); 97 add(RSON,mid+1,r,mid+1,rr,val); 98 } 99 pushup(k,l,r); 100 } 101 } 102 103 int main() { 104 scanf("%d%d",&n,&m); 105 for(int i=1;i<n;i++) { 106 int x,y; 107 scanf("%d%d",&x,&y); 108 add2(x,y); 109 } 110 dfs(1,0); 111 for(int i=1;i<=m;i++) { 112 int x,y; 113 scanf("%d%d",&x,&y); 114 if(dfn[x]>dfn[y]) swap(x,y); 115 if(dfn[x]<=dfn[y] && en[y]<=en[x]) { 116 int LCA=y; 117 for(int j=20;j>=0;j--) if(dep[fa[LCA][j]]>dep[x]) { 118 LCA=fa[LCA][j]; 119 } 120 if(en[LCA]<n) vec_add(en[LCA]+1,n,dfn[y],en[y]); 121 if(dfn[LCA]>1) vec_add(1,dfn[LCA]-1,dfn[y],en[y]); 122 } else vec_add(dfn[x],en[x],dfn[y],en[y]); 123 } 124 125 long long ans=0; 126 for(int i=1;i<=n;i++) { 127 int sz=vec1[i].size(); 128 for(int j=0;j<sz;j++) { 129 int x=vec1[i][j].x; 130 int y=vec1[i][j].y; 131 //cerr<<"????"<<endl; 132 //cerr<<1<<' '<<n<<' '<<x<<' '<<y<<endl; 133 seg::add(1,1,n,x,y,1); 134 //cerr<<"???"<<endl; 135 } 136 sz=vec2[i].size(); 137 for(int j=0;j<sz;j++) { 138 int x=vec2[i][j].x; 139 int y=vec2[i][j].y; 140 seg::add(1,1,n,x,y,-1); 141 } 142 ans+=seg::sum[1]; 143 } 144 ans=(long long) n*(n-1)-ans; 145 cout<<ans<<endl; 146 return 0; 147 }