题解#3

感觉自己弱得没救了。。。求神犇解救T_T

                                                                                                                      7

2597: [Wc2007]剪刀石头布

补集转化之后就是费用流了。我比较逗方案WA了两发。

 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?'
':' ');
92   
93     return 0;
94   
95 }  
View Code

 3813: 奇数国

果真良心送分题,随便写个线段树就可以过了。

 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
",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 }  
View Code

 3870: Our happy ending

T_T没想到状压DP,只想到了爆搜然后多重集合的排列数搞一下。。。没耐心写出来就翻题解了。。。

看代码意思好像不能存在/取出1?

 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 }  
View Code

3826: [Usaco2014 Nov]Cow Jog

我们发现如果两个人起始位置a<b,但终止位置b>a,那么这两人一定会撞车。

所以按起始位置排序,发现就是要求最少单增子序列覆盖=最长不降子序列。

然后就nlogn了。ll的问题WA了好几发。

 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 }
View Code

3825: [Usaco2014 Nov]Marathon

线段树维护一下区间和和区间最大值就好了吧。1A+rank1实在不能再爽。

 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
",getsum(1,1,n,x+1,y)-getmax(1,1,n,x+1,y-1));
61             else if(x+1==y)printf("%d
",dist(a[x],a[y]));
62             else printf("%d
",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 }
View Code

1052: [HAOI2007]覆盖问题

hzwer:

把所有的点用一个最小的矩形圈起来,显然第一个正方形摆在四个角其中的一个,

删去它覆盖的点后,剩下的点变成一个子问题,再放一次正方形,判断下剩下的点是否在一个正方形内

复杂度On

 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 }
View Code

3251: 树上三角形

大于50个点直接输出Y,否则暴力。

 我TM就是个sb,还写了倍增。

 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 }
View Code

相关推荐