4.4

http://codeforces.com/gym/100623/attachments

A题

题意:有n个球(0~n-1)先放在A个盒子(0~A-1)里面,然后将(0~n-1)放在B个盒子(0~B-1),问abs(A盒子所在位置-B盒子所在位置)的和是多少?

思路:现将小球分成两部分(1.k个A与B的公倍数,2.n%(A与B的公倍数)),对于每部分进行模拟解决。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 long long gcd(long long a,long long b)
 8 {
 9     if(b==0) return a;
10     return gcd(b,a%b);
11 }
12 long long solve(long long n,long long a,long long  b)
13 {
14     long long now=0,x=0,y=0,tmp=0,ans=0;
15     while(now<n)
16     {
17         tmp=min(a-x,b-y);
18         if(tmp+now>n) tmp=n-now;
19         ans=ans+tmp*abs(x-y);
20         x=(x+tmp)%a;
21         y=(y+tmp)%b;
22         now=now+tmp;
23     }
24     return ans;
25 }
26 int main()
27 {
28     long long t;
29     scanf("%lld",&t);
30     {
31         long long n,A,B;
32         while(t--)
33         {
34             scanf("%lld%lld%lld",&n,&A,&B);
35             if(A==B)
36             {
37                 printf("0\n");
38                 continue;
39             }
40             long long k=A*B/gcd(A,B);
41             long long ans=0;
42             if(k>n) ans=solve(n,A,B);
43             else ans=n/k*solve(k,A,B)+solve(n%k,A,B);
44             printf("%lld\n",ans);
45         }
46     }
47     return 0;
48 }
View Code

B题

C题

D题

题意:给你n个花盆,然后给你m次操作(1.从p花盆开始将num个花插入花盆,2.询问从 l 到 r 的花盆中有多少朵花),对于操作1打印插入花的起始花盆和结束花盆,对于操作2打印 l 到 r 之间的花朵数量。

思路:可以和容易看出是一道线段树操作的题目,不过在使用线段树的时候要进行二分查找插入花朵的起始位置和结束位置。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 using namespace std;
  8 const int maxn=51000;
  9 struct node
 10 {
 11     int l,r,m,lazy;
 12 } a[maxn<<2];
 13 void build(int l,int r,int k)
 14 {
 15     a[k].l=l,a[k].r=r,a[k].m=0,a[k].lazy=-1;
 16     if(l==r)
 17         return ;
 18     int mid=(l+r)/2;
 19     build(l,mid,k*2);
 20     build(mid+1,r,k*2+1);
 21 }
 22 void push_up(int k)
 23 {
 24     if(a[k].lazy==-1)
 25         return ;
 26     if(a[k].lazy==1)
 27     {
 28         a[k].lazy=-1;
 29         a[k*2].lazy=a[k*2+1].lazy=1;
 30         a[k*2].m=a[k*2].r-a[k*2].l+1;
 31         a[k*2+1].m=a[k*2+1].r-a[k*2+1].l+1;
 32     }
 33     if(a[k].lazy==0)
 34     {
 35         a[k].lazy=-1;
 36         a[k*2].m=a[k*2+1].m=0;
 37         a[k*2].lazy=a[k*2+1].lazy=0;
 38     }
 39 }
 40 void push_down(int k)
 41 {
 42     a[k].m=a[k*2].m+a[k*2+1].m;
 43 }
 44 void ins(int l,int r,int k,int d)
 45 {
 46     if(l<=a[k].l&&a[k].r<=r)
 47     {
 48         a[k].lazy=d;
 49         a[k].m=(a[k].r-a[k].l+1)*d;
 50         return ;
 51     }
 52     push_up(k);
 53     if(r<=a[k*2].r) ins(l,r,k*2,d);
 54     else if(l>=a[k*2+1].l) ins(l,r,k*2+1,d);
 55     else
 56     {
 57         ins(l,r,k*2,d);
 58         ins(l,r,k*2+1,d);
 59     }
 60     push_down(k);
 61     return ;
 62 }
 63 int query(int l,int r,int k)
 64 {
 65     if(l<=a[k].l&&a[k].r<=r)
 66     {
 67         return a[k].m;
 68     }
 69     push_up(k);
 70     int ans=0;
 71     if(r<=a[k*2].r) ans+=query(l,r,k*2);
 72     else if(l>=a[k*2+1].l) ans+=query(l,r,k*2+1);
 73     else
 74     {
 75         ans+=query(l,r,k*2);
 76         ans+=query(l,r,k*2+1);
 77     }
 78     return ans;
 79 }
 80 int main()
 81 {
 82     int n,m,t,x,y,z;
 83     while(~scanf("%d",&t))
 84     {
 85         while(t--)
 86         {
 87             scanf("%d%d",&n,&m);
 88             build(0,n-1,1);
 89             while(m--)
 90             {
 91                 scanf("%d%d%d",&x,&y,&z);
 92                 if(x==1)
 93                 {
 94                     int tmp=(n-y)-query(y,n-1,1);
 95                     if(tmp==0)
 96                     {
 97                         printf("Can not put any one.\n");
 98                         continue;
 99                     }
100                     if(tmp>z)
101                         tmp=z;
102                     int rr=n-1,ll=y,mid;
103                     int l,r;
104                     while(ll<=rr)
105                     {
106                         mid=(ll+rr)/2;
107                         if(mid-y+1-query(y,mid,1)>0)
108                         {
109                             l=mid;
110                             rr=mid-1;
111                         }
112                         else
113                             ll=mid+1;
114                     }
115                     ll=y,rr=n-1;
116                     while(ll<=rr)
117                     {
118                         mid=(ll+rr)/2;
119                         if(mid-y+1-query(y,mid,1)>=tmp)
120                         {
121                             r=mid;
122                             rr=mid-1;
123                         }
124                         else
125                             ll=mid+1;
126                     }
127                     printf("%d %d\n",l,r);
128                     ins(l,r,1,1);
129                 }
130                 else
131                 {
132                     int cnt=query(y,z,1);
133                     printf("%d\n",cnt);
134                     ins(y,z,1,0);
135                 }
136             }
137             printf("\n");
138         }
139     }
140     return 0;
141 }
View Code

E题

F题

G题

H题

题意:给你n行m列的矩阵,当 t 阶方阵中行和列都是对称的时候最大的 t 是多少。

思路:分别求行和列的回文数,然后分别计算行和列的回文数的最小值k,然后求k的最大值

 1 #include <iostream>
 2 #include<cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 using namespace std;
 7 const int inf=0x3f3f3f3f;
 8 const int maxn=1005;
 9 int a[maxn][maxn],num1[maxn][maxn],num2[maxn][maxn];
10 int main()
11 {
12     int n,m,t;
13     while(~scanf("%d",&t))
14     {
15         while(t--)
16         {
17             scanf("%d%d",&n,&m);
18             n=n*2+1;
19             m=m*2+1;
20             for(int i=1;i<=n;i++)
21             {
22                 for(int j=1;j<=m;j++)
23                 {
24                     if(i&1||j&1)
25                         a[i][j]=-1;
26                     else
27                     {
28                         scanf("%d",&a[i][j]);
29                     }
30                 }
31             }
32             int l=0;
33             for(int i=1;i<=n;i++)
34             {
35                 for(int j=1;j<=m;j++)
36                 {
37                     l=0;
38                     for(int k=0;j-k>=1&&j+k<=m;k++)
39                     {
40                         if(a[i][j-k]==a[i][j+k])
41                             l=k;
42                         else
43                             break;
44                     }
45                     num1[i][j]=l;
46                 }
47             }
48             for(int i=1;i<=n;i++)
49             {
50                 for(int j=1;j<=m;j++)
51                 {
52                     l=0;
53                     for(int k=0;i-k>=1&&i+k<=n;k++)
54                     {
55                         if(a[i-k][j]==a[i+k][j])
56                             l=k;
57                         else
58                             break;
59                     }
60                     num2[i][j]=l;
61                 }
62             }
63             int minn,maxx;
64             int ans=0;
65             for(int i=1;i<=n;i++)
66             {
67                 for(int j=1;j<=m;j++)
68                 {
69                     minn=inf,maxx=inf;
70                     for(int k=0;i-k>=1&&i+k<=n&&j-k>=1&&j+k<=m;k++)
71                     {
72                         minn=min(minn,min(num1[i-k][j],num1[i+k][j]));
73                         maxx=min(maxx,min(num2[i][j-k],num2[i][j+k]));
74                         if(minn<k||maxx<k)
75                             break;
76                         ans=max(ans,k);
77                     }
78                 }
79             }
80             printf("%d\n",ans);
81         }
82     }
83     return 0;
84 }
View Code

I题

题意:先输入n和m,然后输入n个点 xi 和 yi 意味着在有一条横向的(xi,yi~xi+1,yi)线段,然后输入m条纵向的线段(xi,yi~~xi,yi+1),问有多少条线段能够独立存在(与其他的线段都不会相连)

思路:先输入n条横向线段,然后找出与m条纵向线段相连的横向线段,然后利用深搜的思想找出和纵向线段相连的而没有和其他纵向线段相连的线段数量。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <queue>
 7 using namespace std;
 8 const int maxn=10005;
 9 vector<int>vec[maxn];
10 int x[maxn],y[maxn],flag[maxn],n,m,cnt[maxn];
11 int solve(int k)
12 {
13     for(int i=0;i<vec[k].size();i++)
14     {
15         int u=vec[k][i];
16         if(!cnt[u])
17         {
18             cnt[u]=1;
19             if(!flag[u]||solve(flag[u]))
20             {
21                 flag[u]=k;
22                 return 1;
23             }
24         }
25     }
26     return 0;
27 }
28 int KM()
29 {
30     int ret=0;
31     memset(flag,0,sizeof(flag));
32     for(int i=1;i<=m;i++)
33     {
34         memset(cnt,0,sizeof(cnt));
35         if(solve(i))
36             ret++;
37     }
38     return ret;
39 }
40 int main()
41 {
42     int a,b;
43     while(~scanf("%d%d",&n,&m))
44     {
45         if(n==0&&m==0)
46         {
47             break;
48         }
49         for(int i=1; i<=n; i++)
50             scanf("%d%d",&x[i],&y[i]);
51         for(int j=1; j<=m; j++)
52         {
53             scanf("%d%d",&a,&b);
54             vec[j].clear();
55             for(int i=1; i<=n; i++)
56                 if((x[i]==a||x[i]+1==a)&&(b==y[i]||b+1==y[i]))
57                     vec[j].push_back(i);
58         }
59         printf("%d\n",n+m-KM());
60     }
61     return 0;
62 }
View Code

J题

posted @ 2017-04-09 19:02  Wally的博客  阅读(143)  评论(0编辑  收藏  举报