今天做了SDOI Day2 觉得自己萌萌哒= =题目真的有点水,一点编程复杂度都没有
T1:星际战争
描述:http://www.lydsy.com/JudgeOnline/problem.php?id=3993
这道题是这两天最容易的题了吧。。
可以发现这是一个二分图,考虑二分答案,那么人们在这段时间的输出伤害就能够确定了,用最大流判断是否所有的机器人护甲值都为0,即可。
数据较良心跑得飞快
Code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 105 7 #define maxm 3000 8 struct edges{ 9 int to,next;double cap; 10 }edge[maxm*2]; 11 int l,next[maxn]; 12 inline void addedge(int x,int y,double z) { 13 l++; 14 edge[l*2]=(edges){y,next[x],z};next[x]=l*2; 15 edge[l*2+1]=(edges){x,next[y],0};next[y]=l*2+1; 16 } 17 int p[maxn],gap[maxn],h[maxn],s,t; 18 double sap(int u,double flow) { 19 if (u==t) return flow; 20 double cnt=0; 21 for (int i=p[u];i;i=edge[i].next) 22 if (edge[i].cap&&h[edge[i].to]+1==h[u]) { 23 double cur=sap(edge[i].to,min(flow-cnt,edge[i].cap)) ; 24 edge[i].cap-=cur;edge[i^1].cap+=cur; 25 p[u]=i; 26 if ((cnt+=cur)==flow) return flow; 27 } 28 if (!(--gap[h[u]])) h[s]=t; 29 gap[++h[u]]++; 30 p[u]=next[u]; 31 return cnt; 32 } 33 inline double maxflow(){ 34 for (int i=1;i<=t;i++) p[i]=next[i]; 35 memset(h,0,sizeof(h)); 36 memset(gap,0,sizeof(gap)); 37 gap[0]=t; 38 double flow=0; 39 while (h[s]<t) flow+=sap(s,1e7); 40 return flow; 41 } 42 int a[maxn],b[maxn]; 43 bool c[maxn][maxn]; 44 int n,m; 45 inline void build(double mid){ 46 l=0; 47 s=n+m+1,t=n+m+2; 48 memset(next,0,sizeof(next)); 49 for (int i=1;i<=n;i++) addedge(s,i,mid*a[i]); 50 for (int i=1;i<=m;i++) addedge(i+n,t,b[i]); 51 for (int i=1;i<=n;i++) 52 for (int j=1;j<=m;j++) 53 if (c[i][j]) addedge(i,j+n,5e6); 54 } 55 int main(){ 56 scanf("%d%d",&m,&n); 57 int sum=0; 58 for (int j=1;j<=m;j++) { 59 scanf("%d",b+j);sum+=b[j]; 60 } 61 for (int i=1;i<=n;i++) scanf("%d",a+i); 62 for (int i=1;i<=n;i++) 63 for (int j=1;j<=m;j++) scanf("%d",c[i]+j); 64 double l=0,r=5e6; 65 while (r-l>1e-4) { 66 double mid=(l+r)/2; 67 build(mid); 68 if (maxflow()<sum) l=mid; 69 else r=mid; 70 } 71 printf("%lf ",r); 72 return 0; 73 }
T2:约数个数和
描述:http://www.lydsy.com/JudgeOnline/problem.php?id=3994
数论渣= =贴下别人的题解吧= =http://blog.codebursts.com/bzoj3994/
顺便说一下自己YY出来的另一种解法,记f[i][j][k]为n=i,m=j中n*m的最小质因数大于pri[k]的答案
那么f[i][j][k]=sigma(f[i/(x^a)][j/(x^b)][k+1]*(a+b+1))
好像很漂亮的样子,但是时间复杂度我不知道怎么样,求大神給我解答QAQ
T3:道路修建
描述:http://www.lydsy.com/JudgeOnline/problem.php?id=3995
看到这个下意识就想到线段树了= =
一共有3种解法
解法一:当合并区间时,连上两条边变成一个环套树,然后删去环上最大的边
我们考虑维护每个区间最左右的一个类似C型结构,可以发现只有当删去的边为纵边同时这个小区间只有一条纵边时大区间的这个东西才会改变,否则都是小区间的左右值。
保存左右两边C的横边最大值以及纵边最大值还有纵边数量即可
解法二:考虑直接生成新区间的树
可以发现这个区间只有可能是或
那么怎么维护这个联通块—联通块的问题呢= =
有3种情况= =
或还有
然后考虑怎么维护联通块—联通块—联通块的问题了= =
我去这怎么办啊
据某位同学透露,这个一共只有3种情况所以可以直接维护(我去我怎么搞出了超多种情况= =,但人家还真的a了而且跑得飞快= =)
具体的实现方法可以私信我
解法三:
可以看出,可能成为树的是该区间的所有点都和暴露在外面的四个点之一相连,所以我们可以考虑用联通性的方法来解决这道题
枚举所有的联通性并考虑转移,还是能写的= =
时间上就有点拙计了
Code:(解法一)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 60010 7 struct bo{ 8 int c[2],cost,mx[2][2];bool flag; 9 }; 10 inline bo update(bo x,bo y){ 11 bo ans; 12 ans.c[0]=y.c[0]; 13 ans.c[1]=y.c[1]; 14 ans.cost=x.cost+y.cost+x.c[0]+x.c[1]; 15 ans.mx[0][0]=x.mx[0][0],ans.mx[0][1]=x.mx[0][1]; 16 ans.mx[1][0]=y.mx[1][0],ans.mx[1][1]=y.mx[1][1]; 17 int tmp=max(max(x.mx[1][0],y.mx[0][0]),max(x.c[0],x.c[1])); 18 if (tmp>=max(x.mx[1][1],y.mx[0][1])) { 19 ans.cost-=tmp;ans.flag=0;return ans; 20 } 21 ans.flag=x.flag&y.flag; 22 if (x.mx[1][1]>y.mx[0][1]) { 23 ans.cost-=x.mx[1][1]; 24 if (x.flag) { 25 ans.mx[0][0]=max(ans.mx[0][0],tmp); 26 ans.mx[0][1]=y.mx[0][1]; 27 } 28 return ans; 29 } 30 ans.cost-=y.mx[0][1]; 31 if (y.flag) { 32 ans.mx[1][0]=max(ans.mx[1][0],tmp); 33 ans.mx[1][1]=x.mx[1][1]; 34 } 35 return ans; 36 } 37 38 int a[maxn][3]; 39 struct node{ 40 int l,r;bo b; 41 }t[maxn*8]; 42 #define mid ((l+r)>>1) 43 #define lc (x<<1) 44 #define rc (lc^1) 45 void build(int x,int l,int r){ 46 t[x].l=l;t[x].r=r; 47 if (l==r) { 48 t[x].b.c[0]=a[l][0]; 49 t[x].b.c[1]=a[l][1]; 50 t[x].b.cost=a[l][2]; 51 t[x].b.flag=1; 52 memset(t[x].b.mx,0,sizeof(t[x].b.mx)); 53 t[x].b.mx[1][1]=t[x].b.mx[0][1]=a[l][2]; 54 return ; 55 } 56 build(lc,l,mid);build(rc,mid+1,r); 57 t[x].b=update(t[lc].b,t[rc].b); 58 } 59 void set(int x,int y){ 60 int l=t[x].l,r=t[x].r; 61 if (l>y||r<y) return ; 62 if (l==r) { 63 t[x].b.c[0]=a[l][0]; 64 t[x].b.c[1]=a[l][1]; 65 t[x].b.cost=a[l][2]; 66 t[x].b.flag=1; 67 memset(t[x].b.mx,0,sizeof(t[x].b.mx)); 68 t[x].b.mx[1][1]=t[x].b.mx[0][1]=a[l][2]; 69 return ; 70 } 71 set(lc,y);set(rc,y); 72 t[x].b=update(t[lc].b,t[rc].b); 73 } 74 bo query(int x,int x1,int y1) { 75 int l=t[x].l,r=t[x].r; 76 if (x1<=l&&r<=y1) return t[x].b; 77 if (y1<=mid) return query(lc,x1,y1); 78 if (mid<x1) return query(rc,x1,y1); 79 return update(query(lc,x1,y1),query(rc,x1,y1)); 80 } 81 int main(){ 82 int n,m; 83 scanf("%d%d",&n,&m); 84 for (int i=1;i<n;i++) scanf("%d",&a[i][0]); 85 for (int i=1;i<n;i++) scanf("%d",&a[i][1]); 86 for (int i=1;i<=n;i++) scanf("%d",&a[i][2]); 87 build(1,1,n); 88 while (m--) { 89 char opt[2]; 90 int x0,x1,y0,y1,z; 91 bo x,y; 92 scanf("%s",opt); 93 switch (opt[0]) { 94 case 'Q' : 95 scanf("%d%d",&x1,&y1); 96 printf("%d ",query(1,x1,y1).cost); 97 break; 98 case 'C': 99 scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&z); 100 if (y0>y1) swap(y0,y1); 101 if (y0==y1) a[y0][2]=z; 102 else a[y0][x0-1]=z; 103 set(1,y0); 104 break; 105 } 106 } 107 return 0; 108 }