题解#3
感觉自己弱得没救了。。。求神犇解救T_T
7
2597: [Wc2007]剪刀石头布
补集转化之后就是费用流了。我比较逗方案WA了两发。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int n,m,k,mincost,tot=1,cnt,s,t,win[maxn],a[maxn][maxn],b[maxn][maxn],head[maxm],d[maxm],from[2*maxm]; 2 3 bool v[maxm]; 4 5 queue<int>q; 6 7 struct edge{int from,go,next,v,c;}e[2*maxm]; 8 9 void add(int x,int y,int v,int c) 10 11 { 12 13 e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot; 14 15 e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot; 16 17 } 18 19 bool spfa() 20 21 { 22 23 for (int i=0;i<=cnt;i++){v[i]=0;d[i]=inf;} 24 25 q.push(s);d[s]=0;v[s]=1; 26 27 while(!q.empty()) 28 29 { 30 31 int x=q.front();q.pop();v[x]=0; 32 33 for (int i=head[x],y;i;i=e[i].next) 34 35 if(e[i].v&&d[x]+e[i].c<d[y=e[i].go]) 36 37 { 38 39 d[y]=d[x]+e[i].c;from[y]=i; 40 41 if(!v[y]){v[y]=1;q.push(y);} 42 43 } 44 45 } 46 47 return d[t]!=inf; 48 49 } 50 51 void mcf() 52 53 { 54 55 while(spfa()) 56 57 { 58 59 int tmp=inf; 60 61 for(int i=from[t];i;i=from[e[i].from]) tmp=min(tmp,e[i].v); 62 63 mincost+=d[t]*tmp; 64 65 for(int i=from[t];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;} 66 67 } 68 69 } 70 71 int main() 72 73 { 74 n=read();s=0;t=n+1;cnt=t; 75 for5(n,n)a[i][j]=read(),win[i]+=(a[i][j]==1); 76 for1(i,n)for1(j,i-1)if(a[i][j]==2) 77 { 78 add(s,++cnt,1,0); 79 b[i][j]=tot+1; 80 add(cnt,i,1,0); 81 add(cnt,j,1,0); 82 } 83 for1(i,n) 84 { 85 mincost+=win[i]*(win[i]-1)/2; 86 for2(j,win[i],n-2)add(i,t,1,j); 87 } 88 mcf(); 89 cout<<(n*(n-1)*(n-2)/6-mincost)<<endl; 90 for1(i,n)for1(j,i-1)if(a[i][j]==2)a[i][j]=!e[b[i][j]].v,a[j][i]=!a[i][j]; 91 for1(i,n)for1(j,n)printf("%d%c",a[i][j],j==n?'\n':' '); 92 93 return 0; 94 95 }
3813: 奇数国
果真良心送分题,随便写个线段树就可以过了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const int p[60]={2,3,5,7,11,13,17,19,23,29, 2 31,37,41,43,47,53,59,61,67, 3 71,73,79,83,89,97,101,103, 4 107,109,113,127,131,137,139, 5 149,151,157,163,167,173,179, 6 181,191,193,197,199,211,223, 7 227,229,233,239,241,251,257, 8 263,269,271,277,281}; 9 struct seg{int s[60];}t[4*maxn]; 10 int n=100000,ret,ans[60]; 11 inline void build(int k,int l,int r) 12 { 13 int mid=(l+r)>>1;t[k].s[1]=r-l+1; 14 if(l==r)return; 15 build(lch);build(rch); 16 } 17 inline void query(int k,int l,int r,int x,int y) 18 { 19 if(l==x&&r==y){for0(i,59)ans[i]+=t[k].s[i];return;} 20 int mid=(l+r)>>1; 21 if(y<=mid)query(lch,x,y); 22 else if(x>mid)query(rch,x,y); 23 else query(lch,x,mid),query(rch,mid+1,y); 24 } 25 inline void pushup(int k) 26 { 27 for0(i,59)t[k].s[i]=t[k<<1].s[i]+t[k<<1|1].s[i]; 28 } 29 inline void change(int k,int l,int r,int x) 30 { 31 if(l==r){for0(i,59)t[k].s[i]=ans[i];return;} 32 int mid=(l+r)>>1; 33 if(x<=mid)change(lch,x);else change(rch,x); 34 pushup(k); 35 } 36 inline int power(int x,int y) 37 { 38 int t=1; 39 for(;y;y>>=1,x=(ll)x*x%mod) 40 if(y&1)t=(ll)t*x%mod; 41 return t; 42 } 43 44 int main() 45 46 { 47 48 freopen("input.txt","r",stdin); 49 50 freopen("output.txt","w",stdout); 51 52 build(1,1,n); 53 int T=read(); 54 while(T--) 55 { 56 int ch=read(),x=read(),y=read(),ret=1; 57 memset(ans,0,sizeof(ans)); 58 if(ch==0) 59 { 60 query(1,1,n,x,y); 61 for0(i,59)if(ans[i])ret=(ll)ret*(p[i]-1)%mod*power(p[i],ans[i]-1)%mod; 62 printf("%d\n",ret); 63 }else 64 { 65 for0(i,59) 66 { 67 while(y%p[i]==0)ans[i]++,y/=p[i]; 68 } 69 change(1,1,n,x); 70 } 71 } 72 73 return 0; 74 75 }
3870: Our happy ending
T_T没想到状压DP,只想到了爆搜然后多重集合的排列数搞一下。。。没耐心写出来就翻题解了。。。
看代码意思好像不能存在/取出1?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int dp[1<<21]; 2 3 int main() 4 5 { 6 7 freopen("input.txt","r",stdin); 8 9 freopen("output.txt","w",stdout); 10 11 int T=read(); 12 while(T--) 13 { 14 int n=read(),l=read(),mx=read(),all=(1<<l)-1; 15 memset(dp,0,sizeof(dp)); 16 dp[0]=1; 17 for1(i,n) 18 for3(j,all,0)if(dp[j]) 19 { 20 int t=dp[j]; 21 for1(k,min(l,k))(dp[all&(j|(j<<k)|(1<<(k-1)))]+=t)%=mod; 22 if(mx>l)dp[j]=(dp[j]+(ll)t*(mx-l)%mod)%mod; 23 } 24 int ans=0; 25 for0(i,all)if(i&(1<<(l-1)))(ans+=dp[i])%=mod; 26 cout<<ans<<endl; 27 } 28 29 return 0; 30 31 }
3826: [Usaco2014 Nov]Cow Jog
我们发现如果两个人起始位置a<b,但终止位置b>a,那么这两人一定会撞车。
所以按起始位置排序,发现就是要求最少单增子序列覆盖=最长不降子序列。
然后就nlogn了。ll的问题WA了好几发。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ll n,m,b[maxn]; 2 pa a[maxn]; 3 int main() 4 { 5 freopen("input.txt","r",stdin); 6 freopen("output.txt","w",stdout); 7 n=read();m=read(); 8 for1(i,n)a[i].first=read(),a[i].second=a[i].first+m*read(); 9 sort(a+1,a+n+1); 10 for1(i,n)b[i]=inf; 11 for1(i,n)b[upper_bound(b+1,b+n+1,-a[i].second)-b]=-a[i].second; 12 for1(i,n)if(b[i]==inf) 13 { 14 cout<<i-1<<endl; 15 return 0; 16 } 17 cout<<n<<endl; 18 return 0; 19 }
3825: [Usaco2014 Nov]Marathon
线段树维护一下区间和和区间最大值就好了吧。1A+rank1实在不能再爽。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct seg{int sum,mx;}t[4*maxn]; 2 struct rec{int x,y;}a[maxn]; 3 inline int dist(rec a,rec b){return abs(a.x-b.x)+abs(a.y-b.y);} 4 int n,m; 5 inline void pushup(int k) 6 { 7 t[k].sum=t[k<<1].sum+t[k<<1|1].sum; 8 t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx); 9 } 10 inline void build(int k,int l,int r) 11 { 12 if(l==r) 13 { 14 t[k].sum=dist(a[l],a[l-1]); 15 t[k].mx=dist(a[l-1],a[l])+dist(a[l],a[l+1])-dist(a[l-1],a[l+1]); 16 return; 17 } 18 build(lch);build(rch); 19 pushup(k); 20 } 21 inline void change(int k,int l,int r,int x) 22 { 23 if(l==r) 24 { 25 t[k].sum=dist(a[l],a[l-1]); 26 t[k].mx=dist(a[l-1],a[l])+dist(a[l],a[l+1])-dist(a[l-1],a[l+1]); 27 return; 28 } 29 if(x<=mid)change(lch,x);else change(rch,x); 30 pushup(k); 31 } 32 inline int getmax(int k,int l,int r,int x,int y) 33 { 34 if(l==x&&r==y)return t[k].mx; 35 if(y<=mid)return getmax(lch,x,y); 36 else if(x>mid)return getmax(rch,x,y); 37 else return max(getmax(lch,x,mid),getmax(rch,mid+1,y)); 38 } 39 inline int getsum(int k,int l,int r,int x,int y) 40 { 41 if(l==x&&r==y)return t[k].sum; 42 if(y<=mid)return getsum(lch,x,y); 43 else if(x>mid)return getsum(rch,x,y); 44 else return getsum(lch,x,mid)+getsum(rch,mid+1,y); 45 } 46 int main() 47 { 48 freopen("input.txt","r",stdin); 49 freopen("output.txt","w",stdout); 50 n=read();m=read(); 51 for1(i,n)a[i].x=read(),a[i].y=read(); 52 build(1,1,n); 53 while(m--) 54 { 55 char ch=getchar(); 56 while(ch!='U'&&ch!='Q')ch=getchar(); 57 if(ch=='Q') 58 { 59 int x=read(),y=read(); 60 if(x+1<=y-1)printf("%d\n",getsum(1,1,n,x+1,y)-getmax(1,1,n,x+1,y-1)); 61 else if(x+1==y)printf("%d\n",dist(a[x],a[y])); 62 else printf("%d\n",0); 63 } 64 else 65 { 66 int x=read(); 67 a[x].x=read();a[x].y=read(); 68 change(1,1,n,x); 69 if(x>1)change(1,1,n,x-1); 70 if(x<n)change(1,1,n,x+1); 71 } 72 } 73 return 0; 74 }
1052: [HAOI2007]覆盖问题
hzwer:
把所有的点用一个最小的矩形圈起来,显然第一个正方形摆在四个角其中的一个,
删去它覆盖的点后,剩下的点变成一个子问题,再放一次正方形,判断下剩下的点是否在一个正方形内
复杂度On
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 struct rec{int x[maxn],y[maxn],top;}a,b; 2 int n,mid; 3 inline void cut(int x1,int x2,int y1,int y2) 4 { 5 int cnt=0; 6 for1(i,b.top) 7 if(b.x[i]<x1||b.x[i]>x2||b.y[i]<y1||b.y[i]>y2)b.x[++cnt]=b.x[i],b.y[cnt]=b.y[i]; 8 b.top=cnt; 9 } 10 inline void solve(int x) 11 { 12 int x1=inf,y1=inf,x2=-inf,y2=-inf; 13 for1(i,b.top) 14 { 15 x1=min(x1,b.x[i]);x2=max(x2,b.x[i]); 16 y1=min(y1,b.y[i]);y2=max(y2,b.y[i]); 17 } 18 if(x==1)cut(x1,x1+mid,y1,y1+mid); 19 if(x==2)cut(x1,x1+mid,y2-mid,y2); 20 if(x==3)cut(x2-mid,x2,y1,y1+mid); 21 if(x==4)cut(x2-mid,x2,y2-mid,y2); 22 } 23 inline bool check() 24 { 25 for1(x,4) 26 for1(y,4) 27 { 28 b.top=a.top; 29 for1(i,b.top)b.x[i]=a.x[i],b.y[i]=a.y[i]; 30 solve(x);solve(y); 31 int x1=inf,y1=inf,x2=-inf,y2=-inf; 32 for1(i,b.top) 33 { 34 x1=min(x1,b.x[i]);x2=max(x2,b.x[i]); 35 y1=min(y1,b.y[i]);y2=max(y2,b.y[i]); 36 } 37 if(x2-x1<=mid&&y2-y1<=mid)return 1; 38 } 39 return 0; 40 } 41 int main() 42 { 43 freopen("input.txt","r",stdin); 44 freopen("output.txt","w",stdout); 45 a.top=n=read(); 46 for1(i,n)a.x[i]=read(),a.y[i]=read(); 47 int l=0,r=inf; 48 while(l<=r) 49 { 50 mid=(l+r)>>1; 51 if(check())r=mid-1;else l=mid+1; 52 } 53 cout<<l<<endl; 54 return 0; 55 }
3251: 树上三角形
大于50个点直接输出Y,否则暴力。
我TM就是个sb,还写了倍增。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int tot,head[maxn],n,m,dep[maxn],a[maxn],b[maxn],f[maxn][21]; 2 struct edge{int go,next;}e[maxn]; 3 inline void add(int x,int y) 4 { 5 e[++tot]=(edge){y,head[x]};head[x]=tot; 6 } 7 inline void dfs(int x) 8 { 9 for1(i,20)if(dep[x]>=1<<i)f[x][i]=f[f[x][i-1]][i-1];else break; 10 for4(i,x) 11 { 12 dep[y]=dep[x]+1;f[y][0]=x;dfs(y); 13 } 14 } 15 inline int lca(int x,int y) 16 { 17 if(dep[x]<dep[y])swap(x,y); 18 int t=dep[x]-dep[y]; 19 for0(i,20)if(t&(1<<i))x=f[x][i]; 20 if(x==y)return x; 21 for3(i,20,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; 22 return f[x][0]; 23 } 24 int main() 25 { 26 freopen("input.txt","r",stdin); 27 freopen("output.txt","w",stdout); 28 n=read();m=read(); 29 for1(i,n)a[i]=read(); 30 for1(i,n-1){int x=read(),y=read();add(x,y);} 31 dep[1]=1; 32 dfs(1); 33 while(m--) 34 { 35 int ch=read(),x=read(),y=read(); 36 if(ch==1)a[x]=y; 37 else 38 { 39 int t=lca(x,y); 40 if(dep[x]-dep[t]+dep[y]-dep[t]+1>=50)puts("Y"); 41 else 42 { 43 int cnt=0; 44 for(int i=x;i!=t;i=f[i][0])b[++cnt]=a[i]; 45 for(int i=y;i!=t;i=f[i][0])b[++cnt]=a[i]; 46 b[++cnt]=a[t]; 47 sort(b+1,b+cnt+1); 48 bool flag=0; 49 for2(i,3,cnt)if((ll)b[i]<(ll)b[i-1]+b[i-2]){flag=1;break;} 50 puts(flag?"Y":"N"); 51 } 52 } 53 } 54 return 0; 55 }