E. Counting Rectangles
标签:二维前缀和
题意:
- 给出n个长方形的长和宽,q次询问 (1≤n≤1e5; 1≤q≤1e5)
- 每次询问给出两个长方形A,B的长和宽(1<=x<=1000)
- 遍历前n个长方形,若长方形A能含于该长方形且该长方形能含于长方体B中, ans += 该长方体面积
- 返回ans
思路:
(nq)一定超时,暴力不行,考虑到长宽较小,采用二维前缀和来写就行
怎么写二维前缀和?把它当作面积来转移就好
代码:
#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int mod=1e9+7;
ll sum[1005][1005],a[1005][1005];
void solve(){
int n,q;
cin>>n>>q;
memset(a,0,sizeof(a));
int x,y;
for(int i=1;i<=n;i++){
cin>>x>>y;
a[x][y] += x*y;
}
for(int i=1;i<=1000;i++){
for(int j=1;j<=1000;j++){
sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a[i][j];
}
}
int a,b,c,d;
while(q--){
cin>>a>>b>>c>>d;
if(a>=c||b>=d) cout<<"0"<<le;
else cout<<sum[c-1][d-1]-sum[c-1][b]-sum[a][d-1]+sum[a][b]<<le;
//宽小于等于a,长小于等于b的都不能取到
}
}
int main() {
int t; cin>>t;
while(t--){
solve();
}
return 0;
}
F. L-shapes
标签:暴力 模拟
题意:
- 给出n行m列的矩阵,*表示有方格,.表示空着
- 2*2的矩阵,若有三个方格,则成为L形
- 若矩阵中只有L型且L型之间不共享边不共享角,或者为空, 则输出YES,反之则NO
思路:
这题我看标签里有dfs,但其实可以直接暴力,因为矩阵挺小(5050)
首先通过遍历查2 * 2的格子,若有L型,判断是否与其他L型相接触,若不接触,则将L型的每个赋值为’1‘,表示为已经访问过的L型,最后再扫一遍矩阵,看看有没有多余的*号
代码:
#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int mod=1e9+7;
char a[55][55];
void solve(){
int n,m;
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
bool f1 = 1,f2 = 1;//f1表示是否只由L构成或者为空,f2表示是否存在不合法的L
int cnt;
for(int i =1;i<=n-1;i++){
for(int j=1;j<=m-1;j++){
cnt = 0;
if(a[i][j]=='*') cnt++;
if(a[i+1][j+1]=='*') cnt++;
if(a[i][j+1]=='*') cnt++;
if(a[i+1][j]=='*') cnt++;
if(cnt==3){
for(int x=i;x<=i+1;x++){
for(int y=j;y<=j+1;y++){
if(a[x][y]=='*'){
for(int u=x-1;u<=x+1;u++){
for(int v=y-1;v<=y+1;v++){
if(a[u][v]=='1') f2 = 0;//查该方格一圈有无其他L
}
}
}
}
}
if(f2){
for(int x=i;x<=i+1;x++){
for(int y=j;y<=j+1;y++){
if(a[x][y]=='*') a[x][y] = '1';
}
}
}
}
if(cnt==4){
f2 = 0;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='*') f1 = 0;
}
}
if(f1&&f2) cout<<"YES"<<le;
else cout<<"NO"<<le;
}
int main() {
fst;
int t; cin>>t;
while(t--){
solve();
}
return 0;
}
G. Even-Odd XOR
标签:构造
题意:
- 给出一个n,让你构造一个数列,要求数列中的数个不行同,且所有奇数位异或运算结果和偶数为相同
思路:
一眼丁真,鉴定为构造题,主要难的地方在于找出规律
当k为4的倍数时 k & (k+3) == (k+1)&(k+2)
接着按模的结果分类讨论构造即可
代码:
#define fst std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout << std::fixed << std::setprecision(20)
#define le "\n"
#define ll long long
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int mod=1e9+7;
void solve(){
ll n;
cin>>n;
ll k=4;
if(n%4==1){
cout<<"0 ";
n--;
}
else if(n%4==2){
cout<<"4 1 2 12 3 8 ";//样例6
n-=6;
k=16;
}
else if(n%4==3){
cout<<"1 3 2 ";
n-=3;
}
while(n>0){
cout<<k<<" "<<k+1<<" "<<k+3<<" "<<k+2<<" ";
k+=4;
n-=4;
}
cout<<le;
}
int main() {
int t; cin>>t;
while(t--){
solve();
}
return 0;
}