<pre name="code" class="cpp">//先上代码,注释稍后奉上。。。 /* 1010 典型线段树 */ #include <stdio.h> #include <iostream> #include <string.h> #include<queue> #include<cmath> using namespace std; struct Tree { int L,R,v; int flag; }tree[100000*4]; void create(int t,int L,int R) { tree[t].L=L; tree[t].R=R; tree[t].flag=0; int mid=(L+R)>>1; if(L==R) {tree[t].v=1;return ;} create(2*t,L,mid); create(2*t+1,mid+1,R); tree[t].v=tree[2*t].v+tree[2*t+1].v; } void down(int t)//释放松弛 { if(tree[t].flag==0)return ; tree[2*t].v=(tree[2*t].R-tree[2*t].L+1)*(tree[t].v/(tree[t].R-tree[t].L+1)); tree[2*t+1].v=(tree[2*t+1].R-tree[2*t+1].L+1)*(tree[t].v/(tree[t].R-tree[t].L+1)); tree[2*t].flag=1; tree[2*t+1].flag=1; tree[t].flag=0; } void up(int t) { if(tree[t].flag)return ; tree[t].v=tree[2*t].v+tree[2*t+1].v; } void update(int t,int L,int R,int v) { //cout<<t<<"#"<<endl; int mid=(tree[t].L+tree[t].R)>>1; if(tree[t].L==L&&tree[t].R==R) { tree[t].v=(tree[t].R-tree[t].L+1)*v; tree[t].flag=1; up(t); return ; } down(t); if(R<=mid) { update(2*t,L,R,v); } else if(L>mid) { update(2*t+1,L,R,v); } else { update(2*t,L,mid,v); update(2*t+1,mid+1,R,v); } up(t); } int n,m,x,y,k; int main() { int ca; scanf("%d",&ca); for(int ii=1;ii<=ca;ii++) { scanf("%d",&n); create(1,1,n); scanf("%d",&m); while(m--) { scanf("%d%d%d",&x,&y,&k); update(1,x,y,k); } printf("Case %d: The total value of the hook is %d.\n",ii,tree[1].v); } return 0; } /* 1009 水题,不解释 */ #include <cstdio> #include <iostream> #include <memory.h> #include <cmath> using namespace std; int vis[90]; int main () { int n,tmp; while(scanf("%d",&n),n) { memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++) { for(int j=0;j<6;j++) {scanf("%d",&tmp); vis[tmp]=1;} } int flag=0; for(int i=1;i<50;i++) if(!vis[i]){flag=1;break;} if(flag)puts("No"); else puts("Yes"); //puts(""); } } /* 1002 穿马甲,带删点的并查集 关键是要把一个元素从集合中取出来。 我们并不关心集合中到底有哪些元素 取出一个元素i可以看成新加了一个点x 把v[i]对应x就ok了 注意如果一个集合的元素全被抽取出来的情况,这个时候集合数量是减少的 判断这种情况只需要记录集合的大小就行了 v[i]=num表示标号为i的点对应于实际的点 */ #include <cstdio> #include <iostream> #include <memory.h> #include <cmath> using namespace std; int fa[2000009]; int v[2000009]; int r[2000009]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void Un(int x,int y) { x=find(x); y=find(y); if(x==y)return ; fa[x]=y; r[y]+=r[x]; } int main () { int n,m; char op[2]; int ca=1; int x,y; while(scanf("%d%d",&n,&m),n+m) { int num=n; for(int i=0;i<n;i++) { v[i]=i; fa[i]=i; r[i]=1;//集合的大小 } while(m--) { scanf("%s",op); if(op[0]=='M') { scanf("%d%d",&x,&y); Un(v[x],v[y]);//查找也是马甲的代表元,好好体会。。。 } else { scanf("%d",&x); fa[num]=num; r[num]=1;//新增一个点num r[find(v[x])]--;//被抽取集合的数量减1 v[x]=num++;//注意对应关系,其实就是穿了一层马甲 } } printf("Case #%d: ",ca++); int ans=0; for(int i=0;i<num;i++) { if(fa[i]==i&&r[i]>0) ans++; } printf("%d\n",ans); } } /* 1004 水题,不解释 可参考coj 1037 */ #include<iostream> #include<vector> #include<string> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; double s[20009],p[20009]; int T,n; double k; int main() { int ca=1; while(scanf("%d%d%lf",&T,&n,&k),T+n+k) { double sum=0; for(int i=0;i<T;i++) { scanf("%lf%lf",&s[i],&p[i]); sum+=(1-p[i]/100.0)*s[i]; } printf("Case %d: %.2lf\n",ca++,sum/k); puts(""); } return 0; } /* 1008 关键是怎么算出相交的面积,具体看注释 */ #include<iostream> #include<vector> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; double x[30],y[30],r[30]; const double PI=acos(-1.0); const double eps=1e-9; int n; double dis(int i,int j) { return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } bool check(double mid,int x) { for(int i=0;i<n;i++)if(i!=x) { double D=dis(x,i); if(mid<D)return false;//mid值没有到达测试圆的圆心,肯定达不到1/2; if(mid>D+r[i])continue;//把整个圆包含了,不必再考虑 double lc=acos((r[i]*r[i]+D*D-mid*mid)/(2.0*r[i]*D)); double s1=lc*r[i]*r[i];//测试圆扇形的面积 double ld=acos((mid*mid+D*D-r[i]*r[i])/(2.0*D*mid)); double s2=ld*mid*mid;//生成圆扇形的面积 double s3=s2-r[i]*D*sin(lc);//生成圆扇形的面积-两个三角形的面积 if(s3+s1<PI*r[i]*r[i]/2.0)return false; } return true; } double solve(int x) { double L=sqrt(2.0)/2.0*r[x],R=10009,mid; while(R-L>eps) { //cout<<R<<endl; mid=(R+L)/2.0; if(check(mid,x))R=mid; else L=mid; } return R; } int main() { int ca; scanf("%d",&ca); while(ca--) { //cout<<PI<<endl; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf%lf",&x[i],&y[i],&r[i]); } double ans=1000009; for(int i=0;i<n;i++) { double tmp=solve(i); if(tmp<ans) ans=tmp; } printf("%.4lf\n",ans); } return 0; } /* 1001 贪心加剪枝 */ #include<iostream> #include<vector> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; int in[1009]; int main() { int ca,n; scanf("%d",&ca); while(ca--) { scanf("%d",&n); int flag=1,sum=0; for(int i=0;i<n;i++) { scanf("%d",&in[i]); if(in[i]>n)flag=0; sum+=in[i]; } if(sum&1)flag=0; if(!flag) puts("no"); else { sort(in,in+n); for(int i=0;i<n;i++)//将最大入度的点和其他点构造边 { for(int j=n-1;j>i&&in[i]>0;j--) { if(in[j]>0) {in[j]--;in[i]--;} } if(in[i]>0)break; sort(in,in+n);//每次取最大 } for(int i=0;i<n;i++) if(in[i]!=0){flag=0;break;} if(!flag)puts("no"); else puts("yes"); } } return 0; } /* 1005 数学题,其实就是均匀分布 */ #include <algorithm> #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <deque> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> using namespace std; int main() { int n,D,ca=1; while (scanf("%d%d",&n,&D),n+D) { int i,j,k; double ans=D; for (i=0;i<n;i++) { double p,L,v; scanf("%lf%lf%lf",&p,&L,&v); ans-=L; ans+=2*L/v;//过河的时间期望 } printf("Case %d: %.3lf\n\n",ca++,ans); } return 0; } /* 1007 大模拟 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<map> using namespace std; int n,T,m; int k,S; int Serv[109]; int isOpen[109][1009]; int trans[109][109]; int work[109]; int now[109]; void init() { int tmp,a,b; scanf("%d%d",&n,&T); scanf("%d%d",&k,&S); memset(Serv,0,sizeof(Serv));//标记是否为服务器 memset(isOpen,0,sizeof(isOpen));//isOpen[i][j]表示机器i在j时间是否开机 memset(now,0,sizeof(now));//机器i当前下载的量 memset(work,-1,sizeof(work));//机器i什么时候开始工作 for(int i=1;i<=k;i++) { scanf("%d",&tmp); Serv[tmp]=1; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",&trans[i][j]); } for(int i=1;i<=n;i++) { scanf("%d",&tmp); while(tmp--) { scanf("%d%d",&a,&b); for(int j=a;j<b;j++) isOpen[i][j]=1;//对于机器i,时间a到b是开机的 } } scanf("%d",&m); while(m--) { scanf("%d%d",&tmp,&a); work[a]=tmp; } } void solve() { for(int i=0;i<T;i++) { for(int j=1;j<=n;j++)//非服务器j从服务器k下载 { if(!Serv[j])continue; if(!isOpen[j][i])continue; for(int k=1;k<=n;k++) { if(i<work[k])continue; if(!isOpen[k][i])continue; if(Serv[k])continue; now[k]+=trans[j][k]; } } for(int j=1;j<=n;j++)//没过1s,将成为服务器的标记 if(now[j]>=S) Serv[j]=1; } for(int i=1;i<=n;i++) { if(Serv[i])puts("100%"); else { double ans=100*now[i]*1.0/S; printf("%d%%\n",(int)ans); } } } int main() { int ca; scanf("%d",&ca); while(ca--) { init(); solve(); } return 0; }
/*1006 树形DP dreamfox版 */ #define M 100005 struct G { int u,w; }; int dp[M],f[M];//dp[x]表示离x的最远节点的距离,f[x]表示最远节点路径上的最近节点标号 int dp2[M],f2[M];//dp2[x]表示离x的次远节点的距离,f[x]表示次远节点路径上的最近节点标号 int Max1,Max2; int p1,p2,n; vector<G> v[M]; void dfs(int pre,int fa,int deg) { int i,j; for (i=0;i<v[fa].size();i++) { int x=v[fa][i].u; if (x==pre) continue; dfs(fa,x,deg+1); if (dp[x]+v[fa][i].w>dp[fa]) { if (dp[fa]>dp2[fa]) { dp2[fa]=dp[fa]; f2[fa]=f[fa]; } dp[fa]=dp[x]+v[fa][i].w; f[fa]=x; } else if (dp[x]+v[fa][i].w>dp2[fa]) { dp2[fa]=dp[x]+v[fa][i].w; f2[fa]=x; } //dp[fa]=max(dp[fa],dp[x]+v[fa][i].w); } } void dfs2(int pre,int fa,int len) { int i,t; if (fa!=1) { if (fa==f[pre]) { if (dp[fa]<dp2[pre]+len) { dp2[fa]=dp[fa]; f2[fa]=f[fa]; dp[fa]=dp2[pre]+len; f[fa]=pre; } else if (dp2[fa]<dp2[pre]+len) { dp2[fa]=dp2[pre]+len; f2[fa]=pre; } } else { if (dp[fa]<dp[pre]+len) { dp2[fa]=dp[fa]; f2[fa]=f[fa]; dp[fa]=dp[pre]+len; f[fa]=pre; } else if (dp2[fa]<dp[pre]+len) { dp2[fa]=dp[pre]+len; f2[fa]=pre; } } } for (i=0;i<v[fa].size();i++) { int x=v[fa][i].u; if (x==pre) continue; dfs2(fa,x,v[fa][i].w); } } int main() { while (scanf("%d",&n)!=EOF) { int i,j; for (i=0;i<=n+1;i++) v[i].clear(); memset(dp,0,sizeof(dp)); memset(dp2,0,sizeof(dp2)); memset(f,0,sizeof(f)); memset(f2,0,sizeof(f2)); for (i=2;i<=n;i++) { int u,w; G t; scanf("%d%d",&u,&w); t.u=u; t.w=w; v[i].push_back(t); t.u=i; v[u].push_back(t); } if (n==1) { printf("0\n"); continue; } dfs(-1,1,0); dfs2(-1,1,0); for (i=1;i<=n;i++) printf("%d\n",dp[i]); } return 0; } //胖华版 //好吧是我的错,加错题了,这是一道经典树状dp,两次dfs,或一次dfs,一次bfs都可以,记录最大的和次小的 #include <cstdio> #include <iostream> #include <memory.h> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAX=10110; int n; int head[MAX]; int qx[MAX], qp[MAX]; int m1[MAX], m2[MAX], s1[MAX], s2[MAX]; int l; int front, rear; struct node { int e, next, v; }edge[MAX*4]; void add_edge(int s, int e, int v) { edge[l].e =e; edge[l].next =head[s]; edge[l].v =v; head[s]=l++; } int dfs(int x, int pre) { int l1; for(int i=head[x];i!=-1;i=edge[i].next ) { int e=edge[i].e ; if(e==pre) continue; l1=dfs(e, x)+edge[i].v ; if(l1>m1[x]) { m2[x]=m1[x], s2[x]=s1[x]; m1[x]=l1, s1[x]=e; } else if(l1>m2[x]) { m2[x]=l1, s2[x]=e; } } return m1[x]; } void bfs() { int x, pre; front=rear=0; qx[rear]=1; qp[rear++]=-1; while(front<rear) { x=qx[front]; pre=qp[front++]; for(int i=head[x];i!=-1;i=edge[i].next ) { int e=edge[i].e ; if(e==pre) continue; int val=edge[i].v ; if(s1[x]==e) { int t=m2[x]+val; if(t>m1[e]) { m2[e]=m1[e], s2[e]=s1[e]; m1[e]=t, s1[e]=x; } else if(t>m2[e]) { m2[e]=t, s2[e]=x; } } else { int t=m1[x]+val; if(t>m1[e]) { m2[e]=m1[e], s2[e]=s1[e]; m1[e]=t, s1[e]=x; } else if(t>m2[e]) { m2[e]=t, s2[e]=x; } } qx[rear]=e; qp[rear++]=x; } } } void init() { int a, b; l=0; memset(head, -1, sizeof(head)); memset(m1, 0, sizeof(m1)); memset(m2, 0, sizeof(m2)); for(int i=2;i<=n;i++) { scanf("%d %d", &a, &b); add_edge(i, a, b); add_edge(a, i, b); } } void solve() { init(); dfs(1, -1); bfs(); for(int i=1;i<=n;i++) printf("%d\n", m1[i]); } int main () { while(scanf("%d", &n)!=EOF) solve(); return 0; }
集训队例赛——20111009 解题报告
最新推荐文章于 2024-08-12 17:23:52 发布