1.三体攻击
这题如果映射到一维的情况下,就是一维差分加二分,那现在就是三维差分加二分了这是第一个难点。
第二个难点就是,坐标要映射一下,因为内存只允许开一维的空间,三维是不可能的。
写法有点复杂 考验码力。
#include <bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int A,B,C,m;
int s[N],b[N],bp[N];
int op[N/2][7];
int d[8][4]={
{0,0,0,1},
{0,0,1,-1},
{0,1,0,-1},
{0,1,1,1},
{1,0,0,-1},
{1,0,1,1},
{1,1,0,1},
{1,1,1,-1},
};
int get(int i,int j,int k)
{
return (i*B+j)*C+k;
}
bool check(int mid)
{
memcpy(b,bp,sizeof b);
for(int i=1;i<=mid;i++)
{
int h=op[i][6];
int x1=op[i][0],x2=op[i][1];
int y1=op[i][2],y2=op[i][3];
int z1=op[i][4],z2=op[i][5];
b[get(x1,y1,z1)]-=h;
b[get(x1, y1, z2 + 1)] += h;
b[get(x1, y2 + 1, z1)] += h;
b[get(x1, y2 + 1, z2 + 1)] -= h;
b[get(x2 + 1, y1, z1)] += h;
b[get(x2 + 1, y1, z2 + 1)] -= h;
b[get(x2 + 1, y2 + 1, z1)] -= h;
b[get(x2 + 1, y2 + 1, z2 + 1)] += h;
}
memset(s, 0, sizeof s);
for (int i = 1; i <= A; i ++) {
for (int j = 1; j <= B; j ++) {
for (int k = 1; k <= C; k ++) {
s[get(i, j, k)] = b[get(i, j, k)];
for (int u = 1; u < 8; u ++ ) {
int x = i - d[u][0];
int y = j - d[u][1];
int z = k - d[u][2];
int t = d[u][3];
s[get(i, j, k)] -= s[get(x, y, z)] * t;
}
if (s[get(i, j, k)] < 0) {
return true;
}
}
}
}
return false;
}
int main()
{
cin>>A>>B>>C>>m;
for(int i=1;i<=A;i++)
for(int j=1;j<=B;j++)
for(int k=1;k<=C;k++)
cin>>s[get(i,j,k)];
for(int i=1;i<=A;i++)
for(int j=1;j<=B;j++)
for(int k=1;k<=C;k++)
{
for(int u=0;u<8;u++)
{
int x=i-d[u][0];
int y=j-d[u][1];
int z=k-d[u][2];
int t=d[u][3];
bp[get(i,j,k)]+=s[get(x,y,z)]*t;
}
}
for(int i=1;i<=m;i++)
for(int j=0;j<7;j++){
cin>>op[i][j];
}
int l=1,r=m;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<r<<endl;
return 0;
}
2.螺旋折线
这题看数据范围就知道是找规律了。但是规律比较难找。

可以用四种方式去划分线段,也可以用线性规划的方式划分线段,比如上方的线段就是
y>x&&y>=-x 以此类推
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int x,y;
cin>>x>>y;
if(abs(x)<=y)
{
int n=y;
cout<<(ll)(2*n-1)*(2*n)+x-(-n)<<endl;
}
else if(abs(y)<=x)
{
int n=x;
cout<<(ll)(2*n)*(2*n)+n-y<<endl;
}
else if(abs(x)<=abs(y)+1&&y<0)
{
int n=abs(y);
cout<<(ll)(2*n)*(2*n+1)+n-x<<endl;
}
else{
int n=abs(x);
cout<<(ll)(2*n-1)*(2*n-1)+y-(-n+1)<<endl;
}
return 0;
}
3.日志统计
双指针的模板应用题捏
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef pair<int,int> PII;
PII a[N];
int n,m,k;
bool st[N];
int cnt[N];
int main()
{
cin>>n>>m>>k;
for(int i=0;i<n;i++)
cin>>a[i].first>>a[i].second;
sort(a,a+n);
for(int i=0,j=0;i<n;i++)
{
cnt[a[i].second]++;
while(a[i].first-a[j].first>=m)
{
cnt[a[j].second]--;
j++;
}
if(cnt[a[i].second]>=k)
st[a[i].second]=true;
}
for(int i=0;i<N;i++)
if(st[i])
{
cout<<i<<endl;
}
return 0;
}
BFS模板题!
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=210;
char g[N][N];
int n,m;
int sx,sy,ex,ey;
int dx[]={0,1,-1,0},dy[]={1,0,0,-1};
int dist[N][N];
int bfs()
{
memset(dist,-1,sizeof dist);
queue<PII> q;
while(q.size())
q.pop();
q.push({sx,sy});
dist[sx][sy]=0;
while(q.size())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x<0||x>=n||y<0||y>=m)
continue;
if(g[x][y]=='#'||dist[x][y]!=-1)
{
continue;
}
dist[x][y]=dist[t.first][t.second]+1;
if(ex==x&&ey==y)
return dist[x][y];
q.push({x,y});
}
}
return -1;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>g[i][j];
if(g[i][j]=='S')
sx=i,sy=j;
else if(g[i][j]=='E')
ex=i,ey=j;
}
int x=bfs();
if(x==-1)
cout<<"oop!"<<endl;
else cout<<x<<endl;
}
return 0;
}
5.红与黑
flood filing捏
#include<iostream>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=30;
char g[N][N];
int n,m;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
bool st[N][N];
int bfs(int x,int y)
{
int cnt=1;
queue<PII> q;
q.push({x,y});
while(q.size())
{
PII t=q.front();
q.pop();
int x=t.x,y=t.y;
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0 || a>=n || b<0 || b>=m) continue;
if(st[a][b]) continue;
if(g[a][b]!='.') continue;
st[a][b]=true;
q.push({a,b});
cnt++;
}
}
return cnt;
}
int main()
{
while(cin>>m>>n,n||m)
{
memset(st,0,sizeof st);
for(int i=0;i<n;i++) scanf("%s",g[i]);
int x,y,flag=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(g[i][j]=='@')
{
x=i,y=j;
flag=1;
}
if(flag) break;
}
cout<< bfs(x,y) <<endl;
}
return 0;
}
6.交换瓶子
置换群解法 用一种特殊的方式画图
将a[i]往a[a[i]]连一条边 这样得到的图都是一些环 我们的目的就是得到n个环 然后交换两个元素不是增加一个环 就是减少一个环 我们的目的是变成n个环 那么答案就是n-k k为环的数量
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+5;
int a[N];
bool st[N];
int main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
int cnt=0;
for(int i=1;i<=n;i++){
if(!st[i]){
cnt++;
for(int j=i;!st[j];j=a[j]){//位置j指向a[j]的元素
st[j]=true;
}
}
}
cout << n-cnt;
}