【纪中受难记】——C3D3:上限还能再高!
T3明明long long,上限只开了1e9,少了70分。
其实差一步就能AK了呢
3831. 地图的密度(MAP)
(File IO): input:map.in output:map.out
Time Limits: 1000 ms Memory Limits: 128000 KB Detailed Limits
Goto ProblemSet
水题,观察样例就知道求得是边长为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 }
3832. 在哪里建酿酒厂(bro)
(File IO): input:bro.in output:bro.out
Time Limits: 1000 ms Memory Limits: 128000 KB Detailed Limits
Goto ProblemSet
我打的是暴力,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 }
1956. 矩形(pro.pas/cpp)
(File IO): input:pro.in output:pro.out
Time Limits: 1000 ms Memory Limits: 128000 KB Detailed Limits
Goto ProblemSet
这题也蛮水,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 }
3833. 平坦的折线(lam)
(File IO): input:lam.in output:lam.out
Time Limits: 1000 ms Memory Limits: 128000 KB Detailed Limits
Goto ProblemSet
有趣的题目。
因为不好整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 }
——抓住了时间,却不会利用的人,终究也逃不过失败的命运。