【纪中受难记】——C3D3:上限还能再高!

T3明明long long,上限只开了1e9,少了70分。

其实差一步就能AK了呢

 


 

 

Description

给出:
        整数n>r>=0,

        由0、1构成的n*n的表格f,行与列用1..n表示,第j列第i行记为f[i,j]。 
        如果[i,j]和[i',j']是表格f中的两格,则他们的距离定义为max(|i-i'|,|j-j'|)。现在需要你计算一个n*n的表格w,w[i,j](表格w中第i列第j行的数)是满足以下条件的f[x,y]的和:[x,y]与[i,j]的距离不大于r。
 
任务:
编一个程序:
        从文件MAP.IN中读入整数n、r以及表格f。
        计算表格w。
        将表格w写入文件MAP.OUT。
 

Input

    在文件MAP.IN的第一行有两个由一个空格隔开的非负整数n、r(0<=r<n<=250)。接下来的n行给出表格f。每一行包括n个数(0或1),分别由一个空格隔开。第j+1行的第i个数表示f[i,j]。

Output

文件MAP.OUT应该包括n行。其中第j行依次给出w[1,j]...w[n,j],分别由一个空格隔开。
 

Sample Input

5 1
1 0 0 0 1
1 1 1 0 0
1 0 0 0 0
0 0 0 1 1
0 1 0 0 0
 

Sample Output

3 4 2 2 1
4 5 2 2 1
3 4 3 3 2
2 2 2 2 2
1 1 2 2 2 
 

Data Constraint

数据规模
对于100%的数据如题目。

水题,观察样例就知道求得是边长为2r+1,以给定点为中心的正方形中1的个数。前缀和优化+n^2过了。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=300;
17 int n,r;
18 int a[N][N];
19 int s[N][N];
20 int getans(int t1,int t2,int t3,int t4){
21     return s[t3][t4]+s[t1-1][t2-1]-s[t1-1][t4]-s[t3][t2-1];
22 }
23 int main(){
24     freopen("map.in","r",stdin);
25     freopen("map.out","w",stdout);
26     n=read(),r=read();
27     for(int i=1;i<=n;i++){
28         for(int j=1;j<=n;j++){
29             a[i][j]=read();
30             s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
31         }
32     }
33     for(int i=1;i<=n;i++){
34         for(int j=1;j<=n;j++){
35             printf("%d ",getans(max(i-r,1),max(j-r,1),min(i+r,n),min(j+r,n)));
36         }
37         printf("\n");
38     }
39     return 0;
40 }

 

 

 

 


 

 

Description

        一个小岛Abstinence上的居民非常喜欢一种不含酒精的啤酒,迄今为止这种不含酒精的啤酒只能从波兰进口。但是今年,Abstinence岛上的一个城市要建一座酿酒厂。所有的城市都坐落于海岸线上,而且它们仅被一条沿着海岸线绕岛一周的公路所连接。酿酒厂的投资商收集了所有城市对这种酒的需求量,即每个城市每天需要多少桶酒。他同时也有一张两个相邻城市之间的距离表。运输上的花费是每桶每英里一元。一天的啤酒运输费用是从酿酒厂将啤酒运送到各个城市所需的费用总和。每天的花费取决于酒厂的位置,投资商希望找到建厂的位置以使每天的运输花费最小。

【任务:】
写一个程序:
      从文本文件BRO.IN中读入城市数,城市间的距离,以及每个城市对酒的日需求量。
      计算每天最少的运输花费。
      将结果写入文件BRO.OUT。
 

Input

        在输入文件的BRO.IN中的第一行包含一个整数n, 5<=n<=10000,表示城市的个数,(我们假设城市沿着公路编号,相邻的城市有相邻的编号,城市1和n也是相邻的)。以下的n行,每行有两个被一个空格隔开的非负整数zi,di,表示第i个城市对啤酒的日需求量和该城市沿高速公路到下一个城市的距离。整条公路的长度不超过1000000英里,每个城市的日需求量不超过1000桶。

Output

你的程序应当在输出文件BRO.OUT中写入一个整数,表示最少可能的每日运输费用。
 

Sample Input

6
1 2
2 3
1 2
5 2
1 10
2 3
 

Sample Output

41
 

Data Constraint

数据规模
对于30%的数据,有N<=30。
对于100%的数据如题目。

 

我打的是暴力,n^2过了10000,下面说一下正解。

大概就是对于在某个点建立酒厂,先确定其他点到它的最短路径是逆时针还是顺时针,可知一定有一个地方将顺逆时针分界,那么移动酒厂位置时,同时移动分界点位置(分界点一定是顺着酒厂方向移动的,不可能相向移动。),数据可以预处理O1算出。

贴一下暴力:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define min(a,b) a<b?a:b
 4 #define max(a,b) a>b?a:b
 5 inline int read(){
 6     int x=0,f=1;
 7     char c=getchar();
 8     while(!isdigit(c)){
 9         if(c=='-') f=-1;
10         c=getchar();
11     }
12     while(isdigit(c)){
13         x=(x<<1)+(x<<3)+(c^48);
14         c=getchar();
15     }
16     return x*f;
17 }
18 const int N=1e4+10;
19 typedef long long ll;
20 int n;
21 int dis[N];
22 int mon[N];
23 int mindis(int x,int y){
24     if(x>y) swap(x,y);
25     return min(dis[y-1]-dis[x-1],dis[n]-dis[y-1]+dis[x-1]);
26     
27 }
28 int main(){
29     freopen("bro.in","r",stdin);
30     freopen("bro.out","w",stdout);
31     n=read();
32     for(register int i=1;i<=n;i++){
33         mon[i]=read();
34         dis[i]=dis[i-1]+read();
35     }
36     ll minans=1e18;
37     for(register int i=1;i<=n;i++){
38         ll ans=0;
39         for(register int j=1;j<=n;j++){
40             ans+=mon[j]*mindis(i,j);
41         }
42         minans=min(minans,ans);
43     }
44     printf("%lld",minans);
45     return 0;
46 }

 


 

 

 

 

Description

现在我们在一个平面上画了n个矩形。每一个矩形的两边都与坐标轴相平行,且矩形定点的坐标均为整数。现我们定义满足如下性质的图形为一个块:
 每一个矩形都是一个块;
 如果两个块有一段公共的部分,那么这两个块就会形成一个新的块,否则这两个块就是不同的。

 示例:
图1中的矩形形成了两个不同的块。
图2中的矩形形成了一个块。

任务:
请写一个程序:
 从文本文件PRO.IN中读入各个矩形的顶点坐标;
 找出这些矩形中不同的块的数目;
 把结果输出到文本文件PRO.OUT中。
 

Input

       在输入文件PRO.IN的第一行又一个整数n,1 <= n <=7000,表示矩形的个数。接下来的n行描述矩形的顶点,每个矩形用四个数来描述:左下顶点坐标(x,y)与右上顶点坐标(x,y)。每个矩形的坐标都是不超过10000的非负整数。

Output

输出唯一的一个整数——这些矩形所形成的不同的块的数目。
 

Sample Input

9
0 3 2 6
4 5 5 7
4 2 6 4
2 0 3 2
5 3 6 4
3 2 5 3
1 4 4 7
0 0 1 4
0 0 4 1

Sample Output

2
 

Data Constraint

数据规模
对于60%的数据,有N<=80
对于100%的数据如题目。

 

这题也蛮水,n^2判断两个矩形是否能合并即可:

  有一个考场上发现的简单方法:

 

1 bool jd(int t1,int t2){
2     int minrux=min(h[t1].ru.x,h[t2].ru.x);
3     int minruy=min(h[t1].ru.y,h[t2].ru.y);
4     int maxldx=max(h[t1].ld.x,h[t2].ld.x);
5     int maxldy=max(h[t1].ld.y,h[t2].ld.y);
6     if((minrux==maxldx&&minruy==maxldy)||minrux<maxldx||minruy<maxldy) return 0;
7     else return 1;
8 }

 

发现这个蓝色的相交部分(两个矩形右上角点的横纵取min,左下角点横纵取max得到)如果是矩形或线段就返回1,否则返回0.

并查集维护即可。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=7010;
17 struct node{
18     int x,y;
19 };
20 int n;
21 struct squre{
22     node ld,ru;
23 }h[N];
24 int fa[N];
25 int find(int x){
26     return x==fa[x]?x:fa[x]=find(fa[x]);
27 }
28 int bul[N];
29 bool jd(int t1,int t2){
30     int minrux=min(h[t1].ru.x,h[t2].ru.x);
31     int minruy=min(h[t1].ru.y,h[t2].ru.y);
32     int maxldx=max(h[t1].ld.x,h[t2].ld.x);
33     int maxldy=max(h[t1].ld.y,h[t2].ld.y);
34     if((minrux==maxldx&&minruy==maxldy)||minrux<maxldx||minruy<maxldy) return 0;
35     else return 1;
36 }
37 int main(){
38 //    freopen("pro.in","r",stdin);
39 //    freopen("pro.out","w",stdout);
40     n=read();
41     for(register int i=1;i<=n;i++){
42         h[i].ld.x=read();
43         h[i].ld.y=read();
44         h[i].ru.x=read();
45         h[i].ru.y=read();
46         fa[i]=i;
47     }
48     for(register int i=1;i<=n;i++){
49         for(register int j=1;j<i;j++){
50             if(jd(i,j)) fa[find(i)]=find(j);
51         }
52     }
53     int ans=0;
54     for(register int i=1;i<=n;i++){
55         if(bul[fa[find(i)]]) continue;
56         else{
57             bul[fa[find(i)]]=1;
58             ans++;
59         }
60     }
61     printf("%d",ans);
62     return 0;
63 }

 

 

 

 


 

 

Description

       现在我们在一张纸上有一个笛卡尔坐标系。我们考虑在这张纸上用铅笔从左到右画的折线。我们要求任何两个点之间连接的直线段与x轴的夹角在-45~45之间,一条满足以上条件的折线称之为平坦的折线。假定给出了n个不同的整点(坐标为整数的点),最少用几条平坦的折线可以覆盖所有的点?


例子:

图中有6个整点:(1,6), (10,8), (1,5), (2,20), (4,4), (6,2),要覆盖它们至少要3条平坦的折线。

 
任务:
写一个程序:
从文件lam.in中读入点的个数以及它们的坐标。
计算最少需要的折线个数。
将结果写入文件lam.out。
 

Input

       在输入文件lam.in的第一行有一个正整数n,不超过30000,代表点的个数。接下来的n行表示这些点的坐标,每行有两个用一个空格隔开的整数x,y,0 <= x <= 30000, 0 <= y <= 30000。第i+1行的数字代表第i个点的坐标。

Output

       在输出文件lam.out的第一行应当有且仅有一个整数——表示覆盖所有的点最少需要的折线数。
 

Sample Input

6
1 6
10 8
1 5
2 20
4 4
6 2
 

Sample Output

3
 

Data Constraint

数据规模
对于20%的数据,有N<=15。
对于100%的数据如题目。

有趣的题目。

因为不好整45度的线,不如直接将坐标轴旋转45度,可以通过如下变换:

 

然后求一个最长下降子序列即可。(参考导弹拦截问题2)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read(){
 4     int x=0,f=1;
 5     char c=getchar();
 6     while(!isdigit(c)){
 7         if(c=='-') f=-1;
 8         c=getchar();
 9     }
10     while(isdigit(c)){
11         x=(x<<1)+(x<<3)+(c^48);
12         c=getchar();
13     }
14     return x*f;
15 }
16 const int N=3e4+10;
17 int n;
18 struct node{
19     int x,y;
20     bool operator < (const node &t)const{
21         if(x==t.x) return y<t.y;
22         else return x<t.x;
23     }
24 }h[N];
25 int c[N],len;
26 int main(){
27     freopen("lam.in","r",stdin);
28     freopen("lam.out","w",stdout);
29     n=read();
30     for(int i=1;i<=n;i++){
31         h[i].x=read();
32         h[i].y=read();
33         int tmp=h[i].x-h[i].y;
34         h[i].y=h[i].x+h[i].y;
35         h[i].x=tmp;
36     }
37     sort(h+1,h+n+1);
38     c[1]=h[1].y;len=1;
39     for(int i=2;i<=n;i++){
40         if(h[i].y<c[len]){
41             c[++len]=h[i].y;
42         }
43         else{
44             int j=lower_bound(c+1,c+len+1,h[i].y,greater<int>())-c;
45             c[j]=h[i].y;
46         }
47     }
48     printf("%d",len);
49     return 0;
50 }

 

posted @ 2019-11-05 15:26  Nelson992770019  阅读(228)  评论(0编辑  收藏  举报