day1 P1
ans = (x + m *(10^k )) %n 10^k %n 用快速幂计算即可
#include
using namespace std;
long long n,m,k,x;
long long power(long long x, long long y, long long n){
long long ans = 1;
while (y){
if(y & 1) ans = ( ans * x) % n;
y/=2; x = (x * x) %n;
}
return ans;
}
int main()
{
cin >> n >> m >> k >> x;
cout << (x + m * ( power( 10 , k , n)) % n) %n << endl;
return 0;
}
day1 P2
(ai-bi)^2 = ai*ai +bi*bi-2ai*bi 最小化结果 显然就是最大化 ai *bi的和,因此我们要找每个ai对应的bi是谁,显然假设ai< aj 那么一定满粗 bi< bj
因为不难证明 如果bi>bj 交换对应关系能使得值更优
那么显然最后问题变成了如何移动b使得移动次数最少,显然根据a我们可以知道每个b最终所在的位置。假设最终所在位置是实际的大小(假设那样是对b的有序化),那么
这个问题就可以转变为求逆序对的问题,就是在那种相对大小的情况下,当前b数组的逆序对。
#include
#include
using namespace std;
const int mod = 99999997;
const int maxn = 1000000+10;
struct Node{
int v,pos;
bool operator<(const Node & o)const{
return v < o.v;
}
}a[maxn],b[maxn];
int c[maxn],id[maxn];
void insert(int x){
for (; x>n;
for (int i = 0; i < n; ++i){
cin >> a[i].v; a[i].pos = i+1;
}
for (int i = 0; i < n; ++i){
cin >> b[i].v; b[i].pos = i+1;
}
sort(a,a+n);
sort(b,b+n);
for (int i = 0; i =1; --i){
ans = (ans+ getSum(id[i])) % mod;
insert(id[i]);
}
cout << ans << endl;
return 0;
}
day1 P3
直接求出最大生成树,然后询问两个节点路径上的最小值即可。求路径上的最小值,因为树是静态的,所有可以求LCA的时候顺便把路上最小值求出来。
可以用倍增算法求,比较简便
#include
#include
#include
#include
#include
#include
using namespace std;
const int INF = 0x7fffffff;
const int maxn = 10000+10;
const int maxm = 50000+10;
struct Edge{
int x,y,w;
bool operator<(const Edge & o)const{
return w > o.w;
}
}e[maxm];
vector v[maxn];
int f[maxn][20],L[maxn][20],father[maxn],dep[maxn];
bool vis[maxn];
int n,m,q,x,y,ans;
void addEdge(int x,int y, int w){
v[x].push_back(y);
v[x].push_back(w);
v[y].push_back(x);
v[y].push_back(w);
}
int find(int x){
if (father[x]==0) return x;
return (father[x] = find( father[x]) );
}
void dfs(int x, int fa){
vis[x] = true;
int len = v[x].size();
for (int i = 0; i < len; i+=2){
int y = v[x][i];
int w = v[x][i+1];
if (y!=fa){
dep[y] = dep[x] + 1;
L[y][0] = w;
f[y][0] = x;
dfs(y,x);
}
}
}
void getMaxPath(){
for (int j = 1; j < 16; ++j)
for (int i = 1; i <= n; ++i){
f[i][j] = f[f[i][j-1]][j-1];
L[i][j] = min(L[i][j-1], L[f[i][j-1]][j-1]);
}
}
int getAns(int x, int y){
if (dep[x] < dep[y]) swap(x,y);
int delta = dep[x] - dep[y];
for (int i = 15; i >=0; i--)
if (delta & (1<=0; i--)
if (f[x][i] != f[y][i]){
ans = min(ans,L[x][i]);
ans = min(ans,L[y][i]);
x = f[x][i];
y = f[y][i];
}
ans = min(ans,L[x][0]);
ans = min(ans,L[y][0]);
return f[x][0];
}
int main()
{
cin>> n >> m;
for (int i = 0 ; i< m; ++i){
scanf("%d %d %d", &e[i].x,&e[i].y,&e[i].w);
}
sort(e,e+m);
for (int i = 0; i < m;++i){
int x = find(e[i].x);
int y = find(e[i].y);
if (x!=y){
addEdge(e[i].x,e[i].y,e[i].w);
father[x] = y;
}
}
memset(father,0,sizeof(father));
for (int i = 1; i <= n; ++i)
for (int j = 0; j <16; ++j) L[i][j] = INF;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; ++i)
if (!vis[i]){
dep[i] = 0;
dfs(i,0);
}
getMaxPath();
cin >> q;
for (int i = 1; i <= q; ++i){
scanf("%d %d",&x, &y);
ans = INF;
if (find(x)!=find(y)) {
int lca = getAns(x,y);
if (lca == 0) ans = -1;
}
printf("%d\n",ans);
}
return 0;
}
day2 P1
一个贪心即可,显然 如果h[i]>h[i-1] 那么 h[i]-h[i-1] 是不得不花新的代价来建造的。否则h[i] 不超过h[i-1]部分可以在h[i-1]部分完成的时候也顺便解决
#include
#include
using namespace std;
int main()
{
int n, h ;
cin >> n;
long long ans = 0;
int last = 0;
for (int i = 0; i < n ; ++i){
scanf("%d", &h);
if ( h > last) ans += h-last;
last = h;
}
cout << ans << endl;
return 0;
}
day2 P2
f[i][1] = max(f[j][0])+1 a[j] f[i][0] = max(f[j][1])+1 a[j]>a[i];
显然类似于LIS问题, 用树状数组或者线段树优化到nlogn 之后想了一下 貌似只要扫一边计算 拐角点的个数就可以了。
#include
#include
#include
using namespace std;
const int maxm = 1000000+10;
const int maxn = 100000+10;
int c0[maxm],c1[maxm], h[maxn];
int n;
void insert(int *c, int x,int val){
for (;x> n ;
int ans = 1;
for (int i = 1; i <= n ; ++i){
scanf("%d", &h[i]); h[i]++;
}
insert(c0,h[1],1);
insert(c1,maxm-1-h[1],1);
for (int i = 2; i <= n; ++i){
int tmp = getMax(c0,h[i]-1);
ans = max(ans,tmp+1);
insert(c1,maxm-1-h[i],tmp+1);
tmp = getMax(c1,maxm-1-h[i] -1);
ans = max(ans,tmp+1);
insert(c0,h[i],tmp+1);
}
cout << ans << endl;
return 0;
}
day2 P3
一道很经典的广搜题 ,需要优化,就是空格一旦确定的情况下,那么其他1的所有位置也确定,并且目标位置的一定必须要把空格先移动过去,
那么这个空格的移动的最少次数我们可以先通过bfs预处理出来。
这样复杂度就是预处理n^4 + qn^2
#include
#include
#include
#include
#include
using namespace std;
const int inf = 0x7fffffff;
const int maxn = 30+5;
const int dir[4][2]={0,-1,0,1,-1,0,1,0};
int mat[maxn][maxn], dis[maxn][maxn][4], step[maxn][maxn][4][4];
int d[maxn][maxn];
int n,m,q,test,ex,ey,sx,sy,tx,ty;
struct node{
int x,y;
};
struct node2{
int x,y,k;
};
bool inside(int x, int y){
return (x>=1 && x <= n && y>= 1 && y <= m);
}
int spfa(){
queue q;
while (!q.empty()) q.pop();
for (int k = 0; k < 4; ++k)
if (dis[sx][sy][k]!=inf)
q.push((node2){sx,sy,k});
while (!q.empty()){
int x = q.front().x;
int y = q.front().y;
int k = q.front().k;
//cout < dis[x][y][k]+step[x][y][k][i] +1) {
dis[_x][_y][i ^ 1] = dis[x][y][k]+step[x][y][k][i] +1;
q.push((node2){_x,_y,i ^ 1 });
}
}
}
int ans = inf;
for (int i = 0; i < 4; ++i)
if (dis[tx][ty][i] < ans) ans = dis[tx][ty][i];
return (ans==inf?-1:ans);
}
int bfs(int sx, int sy, int tx, int ty){
if (!mat[sx][sy]) return inf;
if (!mat[tx][ty]) return inf;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <=m; ++j) d[i][j] = inf;
d[sx][sy] = 0;
queue q;
while (!q.empty()) q.pop();
q.push((node){sx,sy});
while (! q.empty()){
if (d[tx][ty] != inf) return d[tx][ty];
int x = q.front().x;
int y = q.front().y;
q.pop();
for (int i = 0; i < 4; ++i){
int _x = x+dir[i][0];
int _y = y+dir[i][1];
if (inside(_x,_y))
if (mat[_x][_y] && d[_x][_y]==inf){
d[_x][_y] = d[x][y]+1;
q.push((node){_x,_y});
}
}
}
return inf;
}
void init(){
for (int i = 1; i <= n; ++i )
for (int j = 1; j <= m ; ++j){
int v = mat[i][j];
mat[i][j] = 0;
for (int k = 0; k < 4; ++k)
for (int l = 0; l < 4; ++l)
step[i][j][k][l] = bfs(i+dir[k][0],j+dir[k][1],
i+dir[l][0],j+dir[l][1]);
mat[i][j] = v;
}
}
int getAns(){
scanf("%d %d %d %d %d %d", &ex,&ey,&sx,&sy,&tx,&ty);
if (sx ==tx && sy== ty) return 0;
if (sx==ex && sy==ey) return -1;
if (!inside(ex,ey) || !inside(sx,sy) || !inside(tx,ty)) return -1;
if (!mat[ex][ey] || !mat[sx][sy] || !mat[tx][ty]) return -1;
for (int i = 1; i <= n; ++i)
for (int j =1 ; j <= m; ++j)
for (int k = 0; k < 4; ++k)
dis[i][j][k] = inf;
mat[sx][sy] = 0;
for (int k = 0; k < 4; ++k){
dis[sx][sy][k] = bfs(ex,ey,sx+dir[k][0],sy+dir[k][1]);
//cout << k << " "<> n >> m >> test;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m ;++ j)
cin>> mat[i][j];
init();
while (test--)
printf("%d\n",getAns());
return 0;
}