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 '\n'
#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 '\n'
#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 '\n'
#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("\n");
}
return 0;
}