近期刷题记录表

9月14日:  

luogu P1627 [CQOI2009]中位数 

题意:给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。

题解:根据中位数的性质,将大于b的数记为1,小于b的数记为-1,区间和为0的奇数序列即符合题意,再计数即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, b, a[N], lsum[N], rsum[N]; 
int l[N], r[N], minn = N, maxx = 0;
int pos;
ll ans = 0;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){n = read(); b = read();rep(i, 1, n){ a[i] = read();if(a[i] < b) a[i] = -1;if(a[i] == b) a[i] = 0, pos = i;if(a[i] > b) a[i] = 1;}rep(i, pos+1, n) rsum[i] = rsum[i-1] + a[i], minn = min(minn, rsum[i]+n);per(i, pos-1, 1) lsum[i] = lsum[i+1] + a[i], minn = min(minn, lsum[i]+n);l[n] = r[n] = 1;rep(i, pos+1, n) r[rsum[i]+n]++;per(i, pos-1, 1) l[lsum[i]+n]++;maxx = 2*n-minn;rep(i, minn, maxx){ans += (ll)l[i] * r[2*n-i];} printf("%lld\n", ans);return 0;
}
View Code

luogu P3407 散步

题意:数轴上有n个人,每秒钟在给定的方向(向东或向西)移动一个距离,当一个人与一个人相遇时两人不再移动,求t秒后,指定m个人所在的位置。

题解:预处理出相遇点,然后二分答案与pos+t进行比较即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const ll inf = 4557430888798830399;
ll n, t, q;
ll s[N], k = 0;
struct people{ll pos, dic, id; } a[N];
bool mycmp(people a, people b) {return a.pos < b.pos; }
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){n = read(); t = read(); q = read();rep(i, 1, n) a[i].pos = read(), a[i].dic = read(), a[i].id = i;sort(a+1, a+n+1, mycmp);rep(i, 2, n){if(a[i].dic == 2 && a[i-1].dic == 1) s[++k] = (a[i].pos+a[i-1].pos)>>1;}  s[0] = -inf, s[k+1] = inf;rep(i, 1, q){ll x = read();ll posx = a[a[x].id].pos, flag = a[a[x].id].dic;ll l = 1, r = k, mid;while(l < r){mid = (l+r)>>1;if(flag == 1){if(s[mid] < posx) l = mid+1;if(s[mid] > posx) r = mid;}if(flag == 2){if(mid == l) mid++;if(s[mid] < posx) l = mid;if(s[mid] > posx) r = mid-1;}}mid = l;if(s[mid] < posx && flag == 2){if(s[mid+1] < posx && s[mid+1] != inf) mid++;}if(s[mid] > posx && flag == 1){if(s[mid-1] > posx && s[mid-1] != inf) mid--; }if(flag == 1){if(s[mid] > posx+t && s[mid] > posx) printf("%lld\n", posx+t);else if(s[mid] < posx) printf("%lld\n", posx+t);else if(s[mid] < posx+t && s[mid] > posx) printf("%lld\n", s[mid]);else printf("%lld\n", s[mid]);}if(flag == 2){if(s[mid] < posx-t && s[mid] < posx) printf("%lld\n", posx-t);else if(s[mid] > posx-t && s[mid] < posx) printf("%lld\n", s[mid]);else if(s[mid] > posx) printf("%lld\n", posx-t); else printf("%lld\n", s[mid]);}}return 0;
}
View Code

 9月15日:

HLOJ 糖果传递

题意:有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。

题解:环形均分纸牌,只要做过均分纸牌,稍稍分析一下就可以得出结论。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[N], b[N], tot = 0, sum[N];
ll ans, cnt;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read(), tot += a[i];tot /= n;rep(i, 1, n) b[i] = a[i]-tot;rep(i, 1, n) sum[i] = sum[i-1] + b[i];
}
void work(){nth_element(sum+1, sum+(n+1)/2, sum+n+1);cnt = sum[(n+1)/2];rep(i, 1, n) ans += abs(sum[i]-cnt);
}
void print(){printf("%lld\n", ans);
}
int main(){init();work();print();return 0;
}
View Code

 HLOJ The Pilots Brothers refrigerator

题意:给出4×4共16个门把手,改变一个门把手(打开或关闭)需要同时改变同行同列的门把手,当所有门把手都打开时才能打开门。+代表关,-代表开。

题解:要使一个为'+'的符号变为'-',必须其相应的行和列的操作数为奇数;可以证明,如果'+'位置对应的行和列上每一个位置都进行一次操作,则整个图只有这一'+'位置的符号改变,其余都不会改变.

将所有的行和列的位置都加1后,在将其模2之前,对给定的数组状态,将所有的位置操作其所存的操作数个次数,举例,如果a[i][j]==n,则对(i,j)操作n次,当所有的操作完后,即全为‘-’的数组。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
char s[10][10];
int a[10][10], vis[10][10];
int ansx[N], ansy[N], ans = 0, h = 0;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){rep(i, 1, 4) rep(j, 1, 4) cin >> s[i][j];rep(i, 1, 4) rep(j, 1, 4){if(s[i][j] == '+') {a[i][j] ^= 1;rep(k, 1, 4) a[i][k] ^= 1;rep(k, 1, 4) a[k][j] ^= 1; }    }rep(i, 1, 4) rep(j, 1, 4){if(a[i][j]) {ans++;ansx[++h] = i;ansy[h] = j;}}printf("%d\n", ans);rep(i, 1, h) printf("%d %d\n", ansx[i], ansy[i]);return 0;
}
View Code

 HLOJ 占卜DIV

题意(稍稍有点长):

lyd学会了使用扑克DIY占卜。方法如下:一副去掉大小王的扑克共52张,打乱后均分为13堆,编号1~13,每堆4张,其中第13堆称作“生命牌”,也就是说你有4条命。这里边,4张K被称作死神。

 初始状态下,所有的牌背面朝上扣下。

 流程如下:

 1.抽取生命牌中的最上面一张(第一张)。

 2.把这张牌翻开,正面朝上,放到牌上的数字所对应编号的堆的最上边。(例如抽到2,正面朝上放到第2堆牌最上面,又比如抽到J,放到第11堆牌最上边,注意是正面朝上放)

 3.从刚放了牌的那一堆最底下(最后一张)抽取一张牌,重复第2步。(例如你上次抽了2,放到了第二堆顶部,现在抽第二堆最后一张发现是8,又放到第8堆顶部.........)

 4.在抽牌过程中如果抽到K,则称死了一条命,就扔掉K再从第1步开始。

 5.当发现四条命都死了以后,统计现在每堆牌上边正面朝上的牌的数目,只要同一数字的牌出现4张正面朝上的牌(比如4个A),则称“开了一对”,当然4个K是不算的。

 6.统计一共开了多少对,开了0对称作"极凶",1~2对为“大凶”,3对为“凶”,4~5对为“小凶”,6对为“中庸”,7~8对“小吉”,9对为“吉”,10~11为“大吉”,12为“满堂开花,极吉”。

题解:清一色的模拟题,按照题意直接模拟,注意一下细节。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int s[14][5], k[14], sum[15];
int ans = 0;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}int main(){rep(i, 1, 13) rep(j, 1, 4) {char ch;cin >> ch; if(ch == 'A') s[i][j] = 1;else if(ch == '0') s[i][j] = 10;else if(ch == 'J') s[i][j] = 11;else if(ch == 'Q') s[i][j] = 12;else if(ch == 'K') s[i][j] = 13;else s[i][j] = (int)(ch-'0');}rep(i, 1, 13) k[i] = 4;rep(i, 1, 4){int x = s[13][i];while (x != 13) {sum[x]++;x = s[x][k[x]--]; }}rep(i, 1, 14) if (sum[i] == 4) ans++;printf("%d\n", ans);return 0;
}
View Code

 HLOJ solders

题意:这个题目的意思是给你n个士兵在棋盘里的坐标,要你将他们排成连续的一行(即与x轴平行),问你最少要将这些士兵移动多少步。

题解:y坐标取中位数,x坐标转换为右值相等即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, sum = 0, totx = 0, toty = 0;
int x[N], y[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){n = read();rep(i, 1, n) x[i] = read(), y[i] = read();sort(y+1, y+n+1);toty = y[n/2+1];sort(x+1, x+n+1);rep(i, 1, n) x[i] -= (i-1);sort(x+1, x+n+1);totx = x[n/2+1];rep(i, 1, n) sum += abs(totx-x[i]) + abs(toty-y[i]);printf("%d\n", sum);return 0;
}
View Code

HLOJ Sumdiv

题意:求A的B次方mod 1e9 + 7 的值。

题解:对A进行质因子分解,然后推出计算公式,等比数列求和后,求个逆元,再累乘取模即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const ll mod = 1000000007;
const int N = 1e6 + 50;
ll a, b, p[N], c[N], k = 0;
ll ans = 1;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void divide(ll x){rep(i, 2, sqrt(x)) if(x % i == 0) {p[++k] = i; c[k] = 0;while(x % i == 0) x /= i, c[k]++;}if(x > 1) p[++k] = x, c[k] = 1;
}
ll pow(ll a, ll b){ll ans = 1;while(b){if(b & 1) ans = (ans*a)%mod;b >>= 1;a = a*a%mod;}return ans;
}
void work(){rep(i, 1, k){ans = ans*( ( pow( p[i], b*c[i]+1 )-1 )%mod * pow( p[i]-1, mod-2 )%mod)%mod;}
}
int main(){a = read(); b = read();divide(a);    work();if(a == 0) printf("0\n");else printf("%lld\n", (ans+mod)%mod);return 0;
}
View Code

 HLOJ 防线

题意:用三个整数S,E 和D 来描述一组防具,即这一组防具布置在防线的S,S + D,S + 2D,...,S + KD(K∈Z,S + KD≤E,S + (K + 1)D>E)位置上。求某个具有奇数个防具的位置。

题解:整体为二分的思想,二分坐标,l为0, r为最远的点,因为最多只有一个奇数,所以每次二分找区间的数字和是不是奇数即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const ll inf = 9984432123;
ll n, t;
ll e[N],s[N],d[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
ll calc(ll x){ll res = 0;for(int i = 1;i <= n;i++)if(s[i] <= x) res = res+(min(e[i], x)-s[i])/d[i]+1;return res;
}
int main(){t = read();while(t--){n = read();ll l = 0, r;for(int i = 1;i <= n;i++) s[i] = read(), e[i] = read(), d[i] = read(), r = max(r, e[i]);ll ans = 0;while(l <= r){ll mid = (l+r)>>1;if(calc(mid) & 1) r = mid-1, ans = mid;else l = mid+1;}if(!ans) puts("There's no weakness.");else printf("%lld %lld\n", ans, calc(ans)-calc(ans-1));}return 0;
}
View Code

 HLOJ to the max

题意:给定一个n*n的矩阵,求其最大的子矩阵的数字和。(n <= 100)

题解:大水题,预处理前缀和,直接枚举计算,取最大值即可。                                                                                                                                                                      

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[3010][3010];
ll f[3010][3010], ans = 0;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) rep(j, 1, n) a[i][j] = read();f[1][1] = a[1][1];rep(i, 1, n){  f[i][1] = f[i-1][1] + a[i][1]; rep(j, 2, n){f[i][j] = f[i-1][j] + f[i][j-1] + a[i][j] - f[i-1][j-1];}}
}
void work(){ans = a[1][1];rep(i, 1, n) rep(j, 1, n) rep(p, i, n) rep(q, j, n){ll sum = f[p][q] - f[i-1][q] - f[p][j-1] + f[i-1][j-1];ans = max(ans, sum);}
}
void print(){printf("%lld\n", ans);
}
int main(){init();work();print();return 0;
}
View Code

HLOJ Sunscreen

题意:

奶牛们计划着去海滩上享受日光浴。为了避免皮肤被阳光灼伤,所有C(1 <= C <= 2500)头奶牛必须在出门之前在身上抹防晒霜。第i头奶牛适合的最小和最 大的SPF值分别为minSPF_i和maxSPF_i(1 <= minSPF_i <= 1,000; minSPF_i <= maxSPF_i <= 1,000)。如果某头奶牛涂的防晒霜的SPF值过小,那么阳光仍然能 把她的皮肤灼伤;如果防晒霜的SPF值过大,则会使日光浴与躺在屋里睡觉变得 几乎没有差别。为此,奶牛们准备了一大篮子防晒霜,一共L(1 <= L <= 2500)瓶。第i瓶 防晒霜的SPF值为SPF_i(1 <= SPF_i <= 1,000)。瓶子的大小也不一定相同,第i 瓶防晒霜可供cover_i头奶牛使用。当然,每头奶牛只能涂某一个瓶子里的防晒霜 ,而不能把若干个瓶里的混合着用。 请你计算一下,如果使用奶牛们准备的防晒霜,最多有多少奶牛能在不被灼 伤的前提下,享受到日光浴的效果?

简明一点就是:给你若干线段和点,每个点可以与包含这个点的线段匹配,求最大匹配数。

题解:线段按右端点排序,防晒霜按防护值排序,之后进行贪心即可,注意防晒霜的数量。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int k, c, ans = 0;
struct cow{ int l, r; } a[N];
struct node{ int l, r; } b[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
bool cmp1(cow x, cow y){return x.l > y.l;}
bool cmp2(node x, node y){return x.l > y.l;}
int main(){c = read(); k = read();rep(i, 1, c) a[i].l = read(), a[i].r = read();rep(i, 1, k) b[i].l = read(), b[i].r = read();sort(a+1, a+c+1, cmp1);sort(b+1, b+k+1, cmp2);rep(i, 1, c) rep(j, 1, k){if(b[j].l >= a[i].l && b[j].l <= a[i].r && b[j].r) {ans++; b[j].r--;break; }}printf("%d\n", ans);return 0; 
}
View Code

HLOJ Task

题意:有n个机器,m个任务。每个机器至多能完成一个任务。对于每个机器,有一个最大运行时间xi和等级yi,对于每个任务,也有一个运行时间xj和等级yj。只有当xi>=xj且yi>=yj的时候,机器i才能完成任务j,并获得500xj+2yj金钱。问最多能完成几个任务,当出现多种情况时,输出获得金钱最多的情况。

题解:根据任务去选择机器,任务从小到大排列好,遍历的时候。每次先把所有时间大于该任务的机器按照等级存储下来,同等级的机器是等效的,因为只要能完成任务都是等效的,然后取其中恰好大于等于该任务的等级的机器,正确性可以证明。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, m, maxx = 0, ans1, p[N];
ll ans2;
struct node{ int x, y; } a[N];
struct task{ int x, y;} b[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
bool mycmp1(node x, node y){ return (x.x > y.x) || (x.x == y.x && x.y > y.y ); }
bool mycmp2(task x, task y){ return (x.x > y.x) || (x.x == y.x && x.y > y.y ); }
void init(){n = read(); m = read();rep(i, 1, n) a[i].x = read(), a[i].y = read();rep(i, 1, m) b[i].x = read(), b[i].y = read();
}
void work(){sort(a+1, a+n+1, mycmp1);sort(b+1, b+m+1, mycmp2);int j = 1;rep(i, 1, m){while(j <= n && a[j].x >= b[i].x){p[a[j].y] ++;j++;}rep(k, b[i].y, 100){if(p[k]){p[k] --;ans1++; ans2 += (ll)b[i].x*500 + b[i].y * 2;break;}}}
}
void print(){printf("%d %lld\n", ans1, ans2);
}
int main(){init();work();print();return 0;
}
View Code

9月16日

HLOJ 货仓选址

题意:在一条数轴上有N家商店,它们的坐标分别为 A[1]~A[N]。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

题解:大水题,先按坐标排序,取中位数为货仓地址,直接计算即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[N], ans = 0, pos;  
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read();sort(a+1, a+n+1); 
}
void work(){pos = a[n/2+1];rep(i, 1, n) ans += (ll)abs(a[i] - pos);
}
void print(){printf("%lld\n" , ans);
}
int main(){init();work();print();return 0;
}
View Code

HLOJ Corral the Cows

题意:约翰打算建一个围栏来圈养他的奶牛.作为最挑剔的兽类,奶牛们要求这个围栏必须是正方形的,而且围栏里至少要有(1<=C< =500)个草场,来供应她们的午餐. 约翰的土地上共有C<=N<=500)个草场,每个草场在一块1x1的方格内,而且这个方格的 坐标不会超过10000.有时候,会有多个草场在同一个方格内,那他们的坐标就会相同. 告诉约翰,最小的围栏的边长是多少?

题解:考虑将坐标离散化,然后求二维前缀和,由于N<=500,所以离散化后最多也只有1000个点,检验时,我们枚举正方形的左上角,用二分求出它的右下角,然后,判断正方形内是否有大于C的草量。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const int str = 10000;
struct node{ int x, y; } a[N];
int f[3010][3010];
int n, c, minn = N, maxx = 0, ans = 0; 
int px[N], py[N];
int bx[N], by[N], xc, yc;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
bool mycmp(node a, node b){ return a.x < b.x; }
void init(){c = read(), n = read();rep(i, 1, n) a[i].x = read(), a[i].y = read(), px[a[i].x]++, py[a[i].y]++;rep(i, 1, str) {if(px[i]) bx[++xc] = i;px[i] = xc;if(py[i]) by[++yc] = i;py[i] = yc;}rep(i, 1, n) f[px[a[i].x]][py[a[i].y]]++;rep(i, 1, xc) rep(j, 1, yc){f[i][j] += f[i-1][j] + f[i][j-1] - f[i-1][j-1];}
}
bool check(int x){rep(i, px[x], xc) rep(j, py[x], yc){int k = 0, l = 0;if (bx[i] - x >= 0) k = px[bx[i] - x];if (by[j] - x >= 0) l = py[by[j] - x];if (f[i][j] - f[k][j] - f[i][l] + f[k][l] >= c)return 1;}return 0;
}
void work(){int l = 1, r = str;while (l < r) {int mid = (l + r) >> 1;if (check(mid)) r = mid;else l = mid + 1;}ans = l;
}
void print(){printf("%d\n", ans);
} 
int main(){init();work();print(); return 0;
}
View Code

HLOJ Stall Reservation

题意:给出n个区间,第i个区间表示为[li,ri],询问把这些最少的分组数,使得每组内每个区间相离,1<=N<=50,000

题解:按左端点排序

现在来考虑第i个区间的决策点,对于能分进的组j,必然是aj<lj,第i个区间才能被分进去,但是选哪一个组,按照朴素的思想,必然是选aj最小的或者最大的,因为是按左端点排序,后面的区间左端点必然增大,于是前面区间能分进的组,后面的区间也能分进,于是无论选哪一个组都无所谓,如果不能选,必然要新开一个组。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
struct cow{ int l, r, id; } a[N];
int n, k = 0, f[N];
priority_queue < pii, vector< pii >, greater< pii > > q;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
bool mycmp(cow a, cow b){ return (a.l < b.l || (a.l == b.l && a.r < b.r)); }
void init(){n = read();rep(i, 1, n) a[i].l = read(), a[i].r = read(), a[i].id = i;
} 
void work(){sort(a+1, a+n+1, mycmp);q.push(mp(a[1].r, ++k));f[a[1].id] = k;rep(i, 2, n) {if(a[i].l > q.top().first) {int x = q.top().second;q.pop();f[a[i].id] = x;q.push(mp(a[i].r, x));}else {f[a[i].id] = ++k;q.push(mp(a[i].r, k));}}
}
void print(){printf("%d\n", k);rep(i, 1, n) printf("%d\n", f[i]);
}
int main(){init();work();print();return 0;
}
View Code

HLOJ Ultra-QuickSort

题意:给定一个序列,求这个序列的逆序对数。

题解:模板题,直接树状数组求逆序对就莫得了。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[N], c[N];
ll lowbit(ll x){ return x&(-x);}
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void add(ll k, ll v){ while(k <= N) c[k] += v, k += lowbit(k);  }
ll sum(ll k){ll ans = 0;while(k) ans += c[k], k -= lowbit(k);return ans;
}
void init(){while(~scanf("%lld", &n)){if(!n) break;ll ans = 0;memset(c, 0, sizeof(c));rep(i, 1, n) a[i] = read();    per(i, n, 1){if(a[i] == 0) {ans += (ll)i-1;continue;}ans += (ll)sum(a[i]-1);add(a[i], 1); }    printf("%lld\n", ans);}
}
int main(){init();return 0;
}
View Code

HLOJ 奇数码问题

题意:在一个n*n的网格中进行,其中n为奇数,1个空格和1~n*n-1这n*n-1个数恰好不重不漏地分布在n*n的网格中。空格移动的规则与八数码游戏相同,实际上,八数码就是一个n=3的奇数码游戏。现在给定两个奇数码游戏的局面,请判断是否存在一种移动空格的方式,使得其中一个局面可以变化到另一个局面。

题解:当此表达式成立时,状态可达:(状态1奇偶性==状态2奇偶性)==(空格距离%2==0)。若两个状态的可相互到达,则有,两个状态的逆序奇偶性相同且空格距离为偶数,或者,逆序奇偶性不同且空格距离为奇数数。否则不能。逆序对用树状数组求。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, a[N], c[N];
int lowbit(int x){ return x&(-x);}
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void add(int k, int v){ while(k <= n) c[k] += v, k += lowbit(k);  }
int sum(int k){int ans = 0;while(k) ans += c[k], k -= lowbit(k);return ans;
}
int work(){memset(c, 0, sizeof(c));int ans = 0;rep(i, 1, n){a[i] = read();if(!a[i]) continue;ans += sum(n) - sum(a[i]);add(a[i], 1);}return ans&1;
}
void init(){while(~scanf("%d", &n)){n *= n;if(work() == work()) printf("TAK\n");else printf("NTE\n");}
}
int main(){init();return 0;
}
View Code

HLOJ Running Median

题意:你需要写一个程序,读入一个整数序列(在int范围内),每读入奇数个数后输出当前的中位数。

题解:考虑用两个堆来维护,一个大根堆一个小根堆。每次比较两个堆的堆顶,如果不相等就交换堆顶,否则堆顶即为所要求的中位数。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int t, n, m, k;
priority_queue < int, vector<int>, greater<int> > x;
priority_queue < int, vector<int>, less<int> > y;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){t = read();while(t--){m = read(); n = read();printf("%d %d\n", m, n/2+1);k = read();while(x.size()) x.pop();while(y.size()) y.pop();printf("%d ", k);y.push(k);rep(i, 2, n){k = read();if(k > y.top()) x.push(k);else y.push(k);while(abs(x.size()-y.size()) > 1){if(x.size() > y.size()){y.push(x.top());x.pop();}else {x.push(y.top());y.pop();}}if(i & 1){if(y.size() > x.size()) printf("%d ", y.top());else printf("%d ", x.top());}if(i % 20 == 19) printf("\n");}printf("\n");}    return 0;
}
View Code

HLOJ 七夕祭

题意:有一个会场由N排M列共计N×M个摊点组成。但是小LL只对其中的一部分摊点感兴趣。他预先联系了会场的负责人,希望能够通过恰当地布置会场,使得各行中他感兴趣的摊点数一样多,并且各列中他感兴趣的摊点数也一样多。但是摊点已经随意布置完毕了,如果想满足小LL的要求,唯一的调整方式就是交换两个相邻的摊点。两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上,每一行或每一列的第一个位置和最后一个位置也算作相邻。现在小LL想知道他的两个要求最多能满足多少个。在此前提下,至少需要交换多少次摊点。

题解:类似糖果传递,设 bi 的前缀和为 si。如果从第 k 个位置开始,那么第 i 堆和第 i+1 堆交换的纸牌数就是 |si-sk|。总代价就是|s1-sk|+|s2-sk|+|s3-sk|+……+|sn-sk|。发现什么了?当 sk 是 s1~sn 中位数的时候,上式有最小值!所以把 si 排序后,令 sk=s[(n+1)/2],计算代价即可。时间复杂度 O(nlogn),预计得分 100 分。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, m, t, a[N], b[N];
ll ans = 0;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read(); m = read(); t = read();rep(i, 1, t){int x = read(), y = read();a[x]++, b[y]++; }if((t % n != 0) && (t % m != 0)){puts("impossible");exit(0);}
}
void work(){rep(i, 1, n) a[i] -= t/n;rep(i, 1, m) b[i] -= t/m;if(t % n == 0){rep(i, 2, n) a[i] += a[i-1];sort(a+1, a+n+1);rep(i, 1, n) ans += (ll)abs(a[i] - a[(n+1)/2]);}if(t % m == 0){rep(i, 2, m) b[i] += b[i-1];sort(b+1, b+m+1);rep(i, 1, m) ans += (ll)abs(b[i]-b[(m+1)/2]);}
}
void print(){if(t % n != 0) printf("column ");else {if(t % m != 0) printf("row ");else printf("both ");}printf("%lld\n", ans);
}
int main(){init();work();print();return 0;
}
View Code

9月17日

HLOJ Color a Tree

题意:有一棵树,每个节点都有一个代价基值Ci。现在要给每个点染色,第一个染根节点,其余的节点染色的时候其父节点必须已染色。每个节点染色会用掉一个时间单位,每个节点染色的代价是染完此节点时的总时间T*Ci。问染完全部节点所需要的最小代价。

题解:每次找到一个权值最大的节点,如果它是根节点,则首先对它染色,否则的话我们可以得出一个结论,在对它的父亲已经染色的情况下,立刻给它染色是最优的。现在重点讨论第二种情况,当它不是根节点时,我们如果对它父亲染了色,则一定会立刻对它染色,所以可以把它和它父亲合并为同一个节点,它和它父亲的儿子都成为了新节点的儿子,它的父亲的父亲则是新节点的父亲。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, root, a[N], ans;
int head[N], cnt = 0;
struct node{ int to, next, fa, t;double v; 
} e[N];
void add(int x, int y){cnt ++; e[cnt].to = y;e[cnt].next = head[x];head[x] = cnt;
}
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int get(){int res = -1;double sum = 0;rep(i, 1, n) {if(i != root && sum < e[i].v){sum = e[i].v;res = i;}}return res;
}
void init(){n = read(); root = read(); rep(i, 1, n) a[i] = read(), e[i].v = a[i], ans += a[i], e[i].t = 1;rep(i, 1, n-1){int xx, yy;xx = read(); yy = read();add(xx, yy);e[yy].fa = xx;}
}
void work(){rep(i, 1, n-1){int u = get();ans += a[u] * e[e[u].fa].t;e[u].v = -1;rep(j, 1, n) if (e[j].fa == u) e[j].fa = e[u].fa;a[e[u].fa] += a[u];e[e[u].fa].t += e[u].t;e[e[u].fa].v = (double) a[e[u].fa] / e[e[u].fa].t;}    
}
void print(){printf("%d\n", ans);
}
int main(){init();work();print();return 0;
}
View Code

HLOJ 兔子与兔子

题意:很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样。

题解:Hash表模板题,用Hash表存储前缀DNA序列。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
char s[N];
int n, q;
unsigned long long f[N], p[N]; 
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){scanf("%s", s+1); q = read();n = strlen(s+1); p[0] = 1;rep(i, 1, n) {f[i] = f[i-1] * 131 + (s[i]-'a'+1);p[i] = p[i-1] * 131;}
}
void work(){rep(i, 1, q){int l1, l2, r1, r2;l1 = read(); r1 = read(); l2 = read(); r2 = read();if(f[r1] - f[l1-1] * p[r1-l1+1] == f[r2] - f[l2-1] * p[r2-l2+1]){puts("Yes");}else puts("No");}
}
int main(){init();work();return 0;
}
View Code

HLOJ 最大子序和

题意:输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。

题解:对序列进行单调队列维护即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, m, a[N], sum[N];
ll q[N], ans = 0;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read(); m = read();rep(i, 1, n) a[i] = read(), sum[i] = sum[i-1] + a[i];
}
void work(){int l = 1, r = 1;q[1] = 0;rep(i, 1, n) {while(l <= r && q[l] < i - m) l++;ans = max(ans, sum[i] - sum[q[l]]);while(l <= r && sum[q[r]] >= sum[i]) r--;q[++r] = i;}
}
void print(){printf("%lld\n", ans);
}
int main(){init(); work();print();return 0;
}
View Code

HLOJ 无穷的序列

题意:有一个无穷序列如下:110100100010000100000… 请你找出这个无穷序列中指定位置上的数字。

题解:bitset模板题,对序列用bitset维护。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e7 + 50;
int n, a[N], maxn = 0, k;
bitset <100000000> p;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read(), maxn = max(maxn, a[i]);for(int i = 1;i <= maxn; i += k, k++) p.set(i);
}
void print(){rep(i, 1, n) printf("%d\n", p.test(a[i]));
}
int main(){init(); print();return 0;
}
View Code

HLOJ Largest Rectangle in a Histogram

题意:这道题让求直方图中最大的矩形(具体略)。

题解:单调栈模板题,对矩形面积用单调栈维护。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[N], s[N], w[N], p = 0;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){while(~scanf("%d", &n)){if(n == 0) break; ll ans = 0;rep(i, 1, n) a[i] = read();a[n+1] = p = 0;rep(i, 1, n+1){if(a[i] > s[p]) s[++p] = a[i], w[p] = 1;else {int width = 0;while (s[p] > a[i]) {width += w[p];ans = max(ans, (ll)width * s[p]);p--;}s[++p] = a[i], w[p] = width + 1;}}printf("%lld\n", ans);}
}
int main(){init();return 0;
}
View Code

HLOJ Team Queue

题意:有t个团队的人正在排一个长队。每次新来一个人时,如果他有队友在排队,那么这个新人会插队到最后一个队友的身后。如果没有任何一个队友排队,则他会排到长队的队尾。 输入每个团队中所有队员的编号,要求支持如下3种指令(前两种指令可以穿插进行) 对于每个DEQUEUE指令,输出出队人的编号。

题解:队列维护序列,按照题意描述操作序列就行了。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e4 + 50;
int n, m, v[N*N], p, t;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int main(){while(~scanf("%d", &n)){if(n == 0) break;t++; queue <int> q[N];printf("Scenario #%d\n", t);rep(i, 1, n){m = read();rep(j, 1, m) p = read(), v[p] = i;}char ch[100]; int x;while(~scanf("%s", ch)){if(ch[0] == 'S') break;if(ch[0] == 'E') {x = read();if(q[v[x]].empty()) q[0].push(v[x]);q[v[x]].push(x);}if(ch[0] == 'D'){printf("%d\n",q[q[0].front()].front());q[q[0].front()].pop();if(q[q[0].front()].empty()) q[0].pop();}}printf("\n");}return 0;
}
View Code

HLOJ Raid*

题意:给定两组点的坐标,求不在同一组内的点的最小距离。

题解:平面最近点对问题,将同一组内的点的距离赋值为正无穷,分治法求一下平面最近点对即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50, inf = 0x3f3f3f3f;
struct node{ int x, y, id; } a[N], q[N];
int n, t;
double ans; 
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
double dist(node a, node b){ if(a.id == b.id) return 1e9;return sqrt(1.0*(a.x-b.x)*(a.x-b.x) + 1.0*(a.y-b.y)*(a.y-b.y));
}
double MIN(double a, double b){ return a < b ? a : b;}
bool mycmp1(node a, node b){ return a.x < b.x; }
bool mycmp2(node a, node b){ return a.y < b.y; }
double divide(int l, int r){if(l == r) return 1e9;int mid = (l+r)>>1, k = 0;double ans = MIN(divide(l, mid), divide(mid+1, r));rep(i, l, r) if(fabs(a[i].x - a[mid].x) <= ans) q[++k] = a[i];sort(q+1, q+k+1, mycmp2);rep(i, 1, k) rep(j, i+1, k){if(q[j].y - q[i].y <= ans) ans = MIN(ans, dist(q[i], q[j]));}    return ans;
}
int main(){t = read();while(t --> 0){n = read();rep(i, 1, (n<<1)){a[i].x = read(), a[i].y = read();a[i].id = (i <= n)?0:1;}sort(a+1, a+(n<<1)+1, mycmp1);ans = divide(1, (n<<1));printf("%.3lf\n", ans);}return 0;
}
View Code

HLOJ Snowflake Snow Snowflakes

题意:您可能听说没有两个雪花是相似的。 你的任务是编写一个程序来确定这是否真的如此。 您的程序将读取有关雪花集合的信息,并搜索可能相同的一对。 每个雪花都有六个手臂。 对于每个雪花,您的程序将提供六个臂中每个臂的长度的测量。 任何具有相同长度相应臂的雪花都应该被程序标记为可能相同。

题解:在读入一个雪花的时候把这些情况全部放入哈希表中,如果某次插入的时候发生冲突,则说明存在重复的雪花,并且后面的不需要再处理。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e5 + 50;
int n, tot, mod = 99991, snow[N][6], head[N], next[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
int H(int *a){int sum = 0, mul = 1;rep(i, 0, 5){sum = (sum + a[i]) % mod;mul = (ll)mul * a[i] % mod;}return (sum + mul) % mod;
}
bool equal(int *a, int *b){rep(i, 0, 5) rep(j, 0, 5){bool eq = 1;rep(k, 0, 5) if(a[(i+k)%6] != b[(j+k)%6]) eq = 0;if(eq) return 1;eq = 1;rep(k, 0, 5) if(a[(i+k)%6] != b[(j-k+6)%6]) eq = 0;if(eq) return 1;}return 0;
}
bool insert(int *a){int val = H(a);for(int i = head[val];i;i = next[i]){if(equal(snow[i], a)) return 1;}++tot;memcpy(snow[tot], a, 6 * sizeof(int));next[tot] = head[val];head[val] = tot;return 0;
}
int main(){n = read();rep(i, 1, n){int a[10];rep(j, 0, 5) a[j] = read();if(insert(a)){puts("Twin snowflakes found.");return 0;}}puts("No two snowflakes are alike.");return 0;
}
View Code

9月18日

HLOJ 前缀统计

题意:给定N个字符串S1,S2...SN,接下来进行M次询问,每次询问给定一个字符串T,求S1~SN中有多少个字符串是T的前缀。输入字符串的总长度不超过10^6,仅包含小写字母。

题解:Trie树模板题,对于每个询问,在检索过程中累加途径的每个节点的cnt值,就是该询问的答案。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, m, end[N];
int trie[N][26], tot = 1;
char s[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void insert(char* str){int len = strlen(str), p = 1;rep(k, 0, len-1){int ch = str[k] - 'a';if(trie[p][ch] == 0) trie[p][ch] = ++tot;p = trie[p][ch];}end[p]++;
}
int search(char* str){int len = strlen(str), p = 1, res = 0;rep(k, 0, len-1){int ch = s[k] - 'a';if (!trie[p][ch]) break;p = trie[p][ch];res += end[p];}return res;
}
int main(){n = read(); m = read();rep(i, 1, n)  scanf("%s", s), insert(s);rep(i, 1, m) {scanf("%s", s);printf("%d\n", search(s));}return 0;
}
View Code

HLOJ The XOR Largest Pair

题意:在给定的N个整数A1,A2……AN中选出两个进行xor运算,得到的结果最大是多少?

题解:把每个整数看作长度为32的二进制01串(数值较小时在前边补0),并且把A1~Ai-1对应的32位二进制串插入一棵Trie树即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int a[N];
int trie[N*3][2], tot = 0;
int n, ans = 0;
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void insert(int x){int p = 0;per(k, 31, 0){int ch = (x>>k) & 1;if(!trie[p][ch]) trie[p][ch] = ++tot;p = trie[p][ch]; }
}
int search(int x){int p = 0, res = 0;per(k, 31, 0){int ch = (x>>k) & 1;if(trie[p][ch^1]) p = trie[p][ch^1], res = (res<<1) | 1;else p = trie[p][ch], res = (res<<1);}return res;
}
void init(){n = read();rep(i, 1, n) a[i] = read(), insert(a[i]);rep(i, 1, n) ans = max(ans, search(a[i]));
}
void print(){printf("%d\n", ans);
}
int main(){init();print();return 0;
}
View Code

 HLOJ 子序列累加和

题意:现在有N个数的数列。现在你定义一个子序列是数列的连续一部分,子序列的值是这个子序列中最大值和最小值之差。给你这N个数,小x想知道所有子序列的值得累加和是多少

题解:这道题分治应该可以做,不过要学习的是这道题的单调栈做法,就是求出序列的所有max值之和,再求出所有的min值之和,再相减,用单调栈实现序列中每一个数的贡献。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, a[N], s[N], maxl[N], minl[N], maxr[N], minr[N], k = 0;
ll ans = 0; 
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read();
}
void work(){rep(i, 1, n){while(k != 0 && a[s[k]] < a[i]){maxl[i] += maxl[s[k]] + 1;k--; } s[++k] = i;}k = 0;per(i, n, 1){while(k != 0 && a[s[k]] <= a[i]){maxr[i] += maxr[s[k]] + 1;k--; }s[++k] = i;}k = 0;rep(i, 1, n){while (k != 0 && a[s[k]] > a[i]){minl[i] += minl[s[k]] + 1;k--;}s[++k] = i;}k = 0;per(i, n, 1){while (k != 0 && a[s[k]] >= a[i]){minr[i] += minr[s[k]] + 1;k--;}s[++k] = i;}rep(i, 1, n)ans += ((maxl[i]+1)*(maxr[i]+1) - (minl[i]+1)*(minr[i]+1))*a[i];
}
void print(){printf("%lld\n", ans);
}
int main(){init();work();print();return 0;
}
View Code

HLOJ holiday

题意:经过几个月辛勤的工作,FJ决定让奶牛放假。假期可以在1…N天内任意选择一段(需要连续),每一天都有一个享受指数W。但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不能得到足够的休息;假期也不能超过Q天,否则奶牛会玩的腻烦。FJ想知道奶牛们能获得的最大享受指数。

题解:单调队列维护符合条件的序列的单调性。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
ll n, P, Q, a[N], sum[N];
ll q[N], ans = -1e9;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read(), P = read(), Q = read();rep(i, 1, n) a[i] = read();rep(i, 1, n) sum[i] = sum[i-1] + a[i];
}
void work(){int l = 1, r = 0;rep(i, P, n){while(l <= r && sum[q[r]] >= sum[i-P]) r--;q[++r] = i-P;while(l <= r && q[l] < i-Q) l++;ans = max(ans, sum[i] - sum[q[l]]);}
} 
void print(){printf("%lld\n", ans);
}
int main(){init();work(); print();return 0;
}
View Code

9月19日

P3132 [USACO16JAN]愤怒的奶牛Angry Cows

题意:有N个草堆在数轴的不同位置,坐标为x1,x2,….,xn。如果玩家以能量R把奶牛发射到坐标x,就会引爆半径R及以内的的草堆,即坐标范围[x−R,x+R]的草堆都会燃爆,每个被奶牛引爆的草堆又会2次引爆半径R-1及以内的的草堆,2次引爆的草堆又会3次引爆半径R-2及以内的的草堆...直到一次引爆后没有其他草堆被波及或半径为0。

现在只有1头奶牛,能量为R,请计算如果要引爆所有的草堆,最小的R是多少?

题解:用f[i]记录以i为以i为圆心可以向左覆盖前i-1个点的最小半径。 再用g[i]记录以i为圆心可以向右覆盖至第n个点的最小半径,二分答案即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
double eps = 0.001;
double a[N], s[N], maxx = 0, pos, posl, posr;
double vis[N], f[N], g[N];
double ans;
int n;
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read();sort(a+1, a+n+1);rep(i, 2, n) s[i] = a[i] - a[i-1];f[1] = g[n] = 0;rep(i, 2, n){f[i] = 1e9;int l = 1, r = i;while(l + 1 < r){int mid = (l+r)/2;if(f[mid-1] + 1 < a[i]-a[mid-1]) l = mid;else r = mid;}f[i] = min(max(a[i]-a[l-1], f[l-1] + 1), max(a[i] - a[r-1], f[r-1] + 1));}per(i, n-1, 1){g[i] = 1e9;int l = i, r = n - 1;while(l + 1 < r){int mid = (l+r)/2;if(g[mid+1] + 1 < a[mid+1] - a[i]) r = mid;else l = mid;}g[i] = min(max(a[l+1] - a[i], g[l+1] + 1), max(a[r+1] - a[i], g[r+1] + 1));}
}
bool check(double x){ per(i, n, 1){if(f[i] + 1 <= x){for(int j = i;j <= n && a[j] <= a[i] + 2.0*x; j++)if(g[j] + 1 <= x) return true;break;}}return false;
}
void work(){double l = 1.0, r = a[n]*1.0;while(eps < r-l){double mid = (l+r) / 2;if(check(mid)) r = mid;else l = mid;}ans = l;
}
void print(){printf("%.1lf", ans);
}
int main(){init();work();print();return 0;
}
View Code

9月23日

HLOJ Dropping Test

题意:给定你n组ai,bi,让你取出n−k组,使得这nk组的a之和除以b之和最大.

题解:01分数规划模板题,设答案为x, 则 a[i] - b[i] * x 的前n-k组的累加和必须大于等于0。二分答案即可。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const double eps = 1e-9;
const int N = 1e6 + 50;
int n, k;
double a[N], b[N], v[N];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
bool mycmp(double x, double y) {return x > y; }
bool check(double x){double res = 0;rep(i, 1, n) v[i] = a[i] - b[i] * x;sort(v+1, v+n+1, mycmp); rep(i, 1, n-k) res += v[i];return res >= 0;
}
void init(){while(~scanf("%d%d", &n, &k)) {if(n == 0) break;double l = 0, r = 0;rep(i, 1, n) scanf("%lf", &a[i]), r += a[i];rep(i, 1, n) scanf("%lf", &b[i]);while(r-l > eps){double mid = (l+r) / 2;if(check(mid)) l = mid;else r = mid;}printf("%.0lf\n", l * 100);    }
}
int main(){init();return 0;
}
View Code

9月24日

HLOJ 花店橱窗

题意:https://www.luogu.org/problem/P1854 

题解:一道比较显然的DP,设F(i,j)表示到(i,j)位置的最优值,状态转移也非常显然,不再叙述,主要是输出方案值得学习,看代码理解。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, m, a[2010][2010], f[2010][2010];
int ans = -1e9, k[N]; 
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init() {n = read(); m = read();rep(i, 1, n) rep(j, 1, m) a[i][j] = read(), f[i][j] = -1e9;
}
void find(int x, int y){if(x <= 0) return ;int p = x;while(f[x][p] != y) p++;k[x] = p;find(x-1, y-a[x][p]);return ;
}
void work() {rep(i, 1, n) rep(j, 1, m) rep(k, i-1, j-1){f[i][j] = max(f[i][j], f[i-1][k] + a[i][j]);}rep(i, n, m) ans = max(ans, f[n][i]);printf("%d\n", ans);find(n, ans);rep(i, 1, n) printf("%d ", k[i]);printf("\n");
}
int main(){init();work();return 0;
}
View Code

 hnoi2010 合唱队

题意:给定一串序列,问有多少种初始序列经过如题操作可以得到此序列。

题解:f[i][j][1]为可以排成理想队列中[i,j][区间,且以最后一个排进去是第i人的初始队列种数。

f[i][j][0]为可以排成理想队列中[i,j]区间,且以最后一个排进去是第j人的初始队列种数。

限于篇幅,状态转移部分看代码理解。

#include<bits/stdc++.h>#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const int mod = 19650827;
int n, a[N], f[1010][1010][2];
inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f;
}
void init(){n = read();rep(i, 1, n) a[i] = read();rep(i, 1, n) f[i][i][1] = 1;per(l, n, 1) rep(r, l+1, n) {f[l][r][0] = (f[l][r][0] + f[l+1][r][0] * (a[l] < a[l+1]))%mod;f[l][r][0] = (f[l][r][0] + f[l+1][r][1] * (a[l] < a[r]))%mod; f[l][r][1] = (f[l][r][1] + f[l][r-1][0] * (a[r] > a[l]))%mod;f[l][r][1] = (f[l][r][1] + f[l][r-1][1] * (a[r] > a[r-1]))%mod;}printf("%d\n", (f[1][n][1] + f[1][n][0])%mod);
}
int main(){init();return 0;
}
View Code

 

转载于:https://www.cnblogs.com/smilke/p/11523009.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/549521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《性能测试从零开始--LoadRunner入门》读书笔记(四)

终于看完了澳网的赛事了&#xff0c;今天要把第五章的读书笔记完成&#xff0c;哈哈。 4.参数化 书中花了不少力气说明这方面的用法&#xff0c;可见参数化在整个脚本的制作过程中的重要性。在这个session开始的时候&#xff0c;书使用了不少的废话去说明白参数化的意义和参数化…

我的RSS我做主:My RSS

昨天晚上通过google reader 浏览自己的网站时发现&#xff0c;Rss输出的内容比较简单&#xff0c;没有我想输出内容,诸如“评论数”、“评论文章”&#xff0c;“永久链接”等等。修改wordpress RSS 输出函数话&#xff0c;每次更新更新wordpress又要重新改一次&#xff0c;比较…

luogu P3407 散步 二分答案

题目描述 一条道路上&#xff0c;位置点用整数A表示。 当A0时&#xff0c;有一个王宫。当A>0&#xff0c;就是离王宫的东边有A米&#xff0c;当A<0&#xff0c;就是离王宫的西边有A米。 道路上&#xff0c;有N个住宅从西向东用1-N来标号。每个住宅有一个人。住宅只会存在…

网络攻击与防御 实验1

做实验的截图 转载于:https://www.cnblogs.com/ma1998/p/11536582.html

SQL注入原理-手工联合注入查询技术

实验报告记录 得到实验结果 转载于:https://www.cnblogs.com/ma1998/p/11536959.html

51CTO寄来的奖品

这两周都是天天上班面对着电脑,挺无聊的.不过幸好有51CTO与我相伴,一直都在关注51CTO的活动.最近我所在的项目组的老员工个个都新买了笔记本,之前他们所用的旧笔记本自然退还给公司了.呵呵,这样像我这样的新员工就有笔记本分配的了,虽然旧了些还是将就着用了.就这样,回到员工宿…

实验3 SQL注入原理-万能密码注入

实验目的 &#xff08;1&#xff09;理解【万能密码】的原理 &#xff08;2&#xff09;学习【万能密码】的使用 实验原理 一、访问目标网站 1.选择一个存在漏洞的论坛 http://192.168.1.3:8009 进入 2.输入用户名【admin】&#xff0c;密码【2‘ or 1】 转载于:https://www.cn…

[转]使用URLConnection下载文件或图片并保存到本地

Codeimport java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLConnection; /** * 使用URLConnection下载文件或图片并保存到本地。 * * author 老紫竹(laozizhu.com) …

整理了一些t-sql技巧

把长日期转换为短日期 Convert(char(10),getdate(),120) MS-SQL数据库开发常用汇总 1.按姓氏笔画排序:Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as 2.数据库加密:select encrypt(原始密码)select pwdencrypt(原始密码)select pwdcompa…

STM32——IDA反编译 Hex\Bin文件成C代码(转)

转&#xff1a;https://blog.csdn.net/daidi1989/article/details/86304843 IDA是一款功能强大的反编译软件&#xff0c;网上找了许久没找到它的使用教程&#xff0c;经过摸索可将STM32的hex文件进行反汇编&#xff0c;操作步骤如下&#xff0c;首先下载IDA Pro版破解软件&…

STM32——ST-LINK通过BIN文件烧录STM32芯片(转)

转&#xff1a;https://www.cnblogs.com/schips/p/8215711.html 提供2种下载方式 KEIL编译下载 KEIL 5 在开发中还算是比较强大的一种平台。在开发中通过编译再下载会显得很方便。 尽管这个是老生常谈的问题&#xff0c;但还是在这里补全这个设置步骤 1.点击“魔法棒” 2.Debug…

离线应用架构

看完了Google的官方架构文档&#xff08; [url]http://code.google.com/apis/gears/architecture.html[/url]&#xff09;&#xff0c; 结合了Modal和Modeless两种优点&#xff0c;总结出如下架构模式&#xff1a;这种架构的好处是&#xff0c;用户总是把数据存在本地&#xff…

突破PTU网页认证校园网开热点

人总有浮躁&#xff0c; 之前只是把脚本写好&#xff0c;没有实操过。 [这是更新过的教程&#xff0c;保证只要按教程走一定可以--->运行成功] 教程可能有些生涩&#xff0c;需要一点耐心 ###ps&#xff1a;不保证热点不出现断网情况【此时手机WiFi关开一次既解决】 教程篇 …

PowerDesigner 导入sql脚本到MySQL乱码问题

为什么80%的码农都做不了架构师&#xff1f;>>> PowerDesigner 12.5 / MySQL 5.0.22 通过PowerDesigner生成MySQL5的数据库脚本。因为对MySQL的命令不熟悉&#xff0c;所以就下载了一个MySQL UI TOOLS。想着通过MySQL Query Browser来执行SQL脚本。 安装好之后&…

安装Windows 2003 域控制器

操作系统要求&#xff1a;Windows 2003 Server StdWindows 2003 Server EntWindows 2003 Server Dc相关配置要求&#xff1a;DNS服务器转载于:https://blog.51cto.com/handongliu/141779

域控制器的强制卸载,Active Directory系列之十四

域控制器的强制卸载上篇博文中我们介绍了如何对域控制器进行常规卸载&#xff0c;本文中我们将介绍如何对域控制器进行强制卸载。为什么需要对域控制器进行强制卸载呢&#xff1f;如果域控制器不能和复制伙伴正常通讯&#xff0c;而且更正无望&#xff0c;那我们就要考虑进行强…

题解 [SHOI2014]概率充电器

前情提要&#xff1a;最近大佬们都在写题解&#xff0c;只有我在咕咕咕。QAQ&#xff1b;明明我都把flag写出来辣&#xff0c;dalao们没看见&#xff0c;然后就被嘲讽了,QAQ 洛谷 树形DP期望&#xff08;讲了两次&#xff0c;菜鸡的我才做&#xff31;&#xff21;&#xff31;…

AtCoderGC038B - Sorting a Segment 数据结构 + RMQ

题意&#xff1a;给定一个长度为N的排列&#xff0c;你只能对其中长度为K的连续子序列进行一次从小到大的排序&#xff0c;问&#xff1a;排序之后能形成多少不同的排列&#xff1f; 数据范围&#xff1a; 1 < n, k < 200,000&#xff0c; k < n. -------------------…

luogu P2216 [HAOI2007]理想的正方形 递推+ST表

题意&#xff1a;有一个a*b的整数组成的矩阵&#xff0c;现请你从中找出一个n*n的正方形区域&#xff0c;使得该区域所有数中的最大值和最小值的差最小。 数据规模&#xff1a; &#xff08;1&#xff09;矩阵中的所有数都不超过1,000,000,000 &#xff08;2&#xff09;20%的数…

[USACO12MAR]花盆Flowerpot 二分答案+单调队列

题意&#xff1a; 给出N滴水的坐标&#xff0c;y表示水滴的高度&#xff0c;x表示它下落到x轴的位置。 每滴水以每秒1个单位长度的速度下落。你需要把花盆放在x轴上的某个位置&#xff0c;使得从被花盆接着的第1滴水开始&#xff0c;到被花盆接着的最后1滴水结束&#xff0c;之…