A. Cancel the Trains
签到题,看两边有无相同相对位置出发的,加入计数即可。
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
int main()
{
int kase;
cin>>kase;
while(kase--)
{
ll n = read(), m = read();
map<ll,ll> vis;
rep(i,1,n)
{
ll x = read();
vis[x] = 1;
}
ll cnt = 0;
rep(i,1,m)
{
ll x = read();
if(vis[x]) cnt++;
}
cout<<cnt<<endl;
}
return 0;
}
B. Suffix Operations
题意:每次可以对任意后缀+1或者-1,在操作前你可以将任意一个数改变成任何数。问你最小操作次数使得数列全部相等。
思路:
首先观察通过后缀来改变数组,会有什么性质。
首先,若先不考虑把一个数换掉,要想把所有数变得相等,因为最优肯定是变成最大最小值之间的一个数(不然还要多花步数),所以要花的次数肯定是数组的差分和。
现在我们改变一个数的效果是什么?我们看一下三个例子
7 5 3 (从后往前递增)
把5改成【3,7】之间的都是最优的
3 5 7 (从后往前递减)
同上
7 3 5 (中间“断崖”)
显然5会经历先变成3再一起变成7的过程,这里就浪费了掉到3的步数,这个时候把3换成【5,7】之间的数就同上了。
所以换数产生更优方法的地方就在于消除“断崖”。 而这个过程又相当于“去掉了”这个数。
所以我们再处理完差分和的时候,遍历一遍去掉哪个数最优即可~
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll a[maxn];
ll res[maxn];
int main()
{
int kase;
cin>>kase;
while(kase--)
{
ll n = read();
rep(i,1,n) a[i] = read();
ll cnt = 0;
ll pre = a[n];
a[n+1] = a[n-1];
a[0] = a[2];
per(i,n,1)
{
res[i] = abs(a[i]-pre);
cnt += res[i];
pre = a[i];
}
ll mi = cnt;
res[0] = 0;
per(i,n,1)
{
mi = min(mi,cnt-res[i]-res[i-1]+abs(a[i-1]-a[i+1]));
}
cout<<mi<<endl;
}
return 0;
}
C. Triangles
思路:这个题竟然n方的算法会T,吐了。这里讲一下优化后的方法。
先把0~9各自出现的坐标记录下来。然后从0到9遍历,对于每个数我们贪心的策略肯定是
选出最远的两个x,他们彼此之间的距离当做高,然后选其中一个的y坐标和边界的距离当底。
或者选出最远的两个y,彼此距离当搞,选其中一个x和边界距离当底。
所以就对每个数的所有坐标先进行x排序,再进行y排序。分别固定最远的两个点遍历一遍另一个点,执行上述操作即可。(个人感觉有点麻烦)
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn = 5000+200;
const int maxn1 = 5e6;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline int read(){ int f = 1; int x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
char s[maxn][maxn];
vector<vector<PII> > Map(15);
typedef struct Pos
{
int x;
int y;
}P;
P row[maxn1];
P col[maxn1];
bool cmp1(P a, P b)
{
return a.x < b.x;
}
bool cmp2(P a, P b)
{
return a.y < b.y;
}
int main()
{
int kase;
kase = read();
while(kase--)
{
int n = read();
rep(i,0,10) Map[i].clear();
rep(i,1,n)
{
gets(s[i]+1);
}
rep(i,1,n) rep(j,1,n) Map[s[i][j]-'0'].pb(mp(i,j));
rep(cur,0,9)
{
int ma = 0;
int p1 = 0;
int p2 = 0;
for(int i=0; i<Map[cur].size(); ++i)
{
row[++p1].x = Map[cur][i].fi;
row[p1].y = Map[cur][i].se;
col[++p2].x = Map[cur][i].fi;
col[p2].y = Map[cur][i].se;
}
sort(row+1,row+1+p1, cmp1);
sort(col+1,col+1+p2, cmp2);
if(p1>=2)
{
rep(i,2,p1)
{
ma = max(ma, max( (row[i].x-row[1].x)*(row[i].y-1),(row[i].x-row[1].x)*(n-row[i].y) ) );
ma = max(ma, max( (row[i].x-row[1].x)*(row[1].y-1),(row[i].x-row[1].x)*(n-row[1].y) ) );
}
per(i,p1-1,1)
{
ma = max(ma, max((row[p1].x-row[i].x)*(row[i].y-1),(row[p1].x-row[i].x)*(n-row[i].y) ));
ma = max(ma, max((row[p1].x-row[i].x)*(row[p1].y-1),(row[p1].x-row[i].x)*(n-row[p1].y) ));
}
}
if(p2>=2)
{
rep(i,2,p2)
{
ma = max(ma, max((col[i].y-col[1].y)*(col[i].x-1), (col[i].y - col[1].y)*(n-col[i].x) ));
ma = max(ma, max((col[i].y-col[1].y)*(col[1].x-1), (col[i].y - col[1].y)*(n-col[1].x) ));
}
per(i,p2-1,1)
{
ma = max( ma, max((col[p2].y-col[i].y)*(col[i].x-1), (col[p2].y - col[i].y)*(n-col[i].x) ) );
ma = max( ma, max((col[p2].y-col[i].y)*(col[p2].x-1), (col[p2].y - col[i].y)*(n-col[p2].x) ) );
}
}
printf("%d ",ma);
}
printf("
");
}
return 0;
}