找出最长的和后缀相等的前缀,反复输出除去前缀的剩下部分即可啦。
#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = (int)1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n, k;
char str[nmax];
int main() {
while (scanf("%d %d", &n, &k) != EOF) {
scanf("%s", str + 1);
int ans = 0;
for(int len = n - 1; len >= 1; -- len) {
bool isok = true;
for(int i = 1; i <= len; ++i)
if(str[i] != str[n - len + i]) {
isok = false;
break;
}
if(isok) {
ans = len;
break;
}
}
// printf("debug %d\n", ans);
printf("%s", str + 1);
for(int i = 1; i < k; ++i) {
for(int j = ans + 1; j <= n; ++j) {
printf("%c", str[j]);
}
}
}
return 0;
}
用队列存一下当前数字的目标(即数字的两倍)。每次判断一个数字是否小于等于当前队列的队头,若是的话,那么说明可以找到一个数字满足上一个数字的要求,那么上一个数字的目标(即他的两倍)出队,计数器加一。 若不满足要求的话,让上一个数字做为序列的尾部,因为他可以满足找不到数字满足要求。一边统计一边更新答案即可。
注意最后队列里还有元素,计数器还要加一,同时更新答案。否则会漏掉答案出现在序列末尾的情况。
#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n;
int a[nmax];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
queue<int> q;
int cnt = 0, ans = 0;
for(int i = 1; i <= n; ++i) {
if(q.empty()) {
q.push(2 * a[i]);
} else {
int now = q.front();
if(a[i] <= now) {
q.pop();
cnt ++;
q.push(2 * a[i]);
} else {
ans = max(ans, cnt + 1);
while(!q.empty()) q.pop();
q.push(2 * a[i]);
cnt = 0;
}
}
}
if(!q.empty()) {
ans = max(ans, cnt + 1);
}
printf("%d\n" ,ans);
return 0;
}
对于 n n 个序列的相交部分,可以认为是 n n 个序列的左端点的最大值和右端点的最小值的差。如果左端点最大值还比右端点最小值大,说明没有相交的部分。
所以对于左右端点分别来看,ST预处理左端点的最大值和右端点的最小值,每次只需要看一下 max([l1,li−1],[ii+1,in]) m a x ( [ l 1 , l i − 1 ] , [ i i + 1 , i n ] ) 与 min([r1,ri−1],[ri+1,rn]) m i n ( [ r 1 , r i − 1 ] , [ r i + 1 , r n ] ) 的相交情况,更新答案。
#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n;
int l[nmax], r[nmax];
int dpl[nmax][(int)(log2(1e6+7) + 10)], dpr[nmax][(int)(log2(1e6+7) + 10)];
void getRMQ() {
for (int i = 1; i <= n; ++i)
dpl[i][0] = l[i];
for (int j = 1; (1 << j) <= n ; ++j)
for (int i = 1; i + ( 1 << j ) - 1 <= n; ++i)
dpl[i][j] = max(dpl[i][j - 1], dpl[i + (1 << (j - 1 ))][j - 1]);
for (int i = 1; i <= n; ++i)
dpr[i][0] = r[i];
for (int j = 1; (1 << j) <= n ; ++j)
for (int i = 1; i + ( 1 << j ) - 1 <= n; ++i)
dpr[i][j] = min(dpr[i][j - 1], dpr[i + (1 << (j - 1 ))][j - 1]);
}
int RMQmax(int l, int r) {
int k = 0;
while ( (1 << (k + 1)) <= r - l + 1) ++k;
return max(dpl[l][k], dpl[r - (1 << k) + 1][k]);
}
int RMQmin(int l, int r) {
int k = 0;
while ( (1 << (k + 1)) <= r - l + 1) ++k;
return min(dpr[l][k], dpr[r - (1 << k) + 1][k]);
}
int getans(int l, int r) {
if(r <= l) return 0;
else return r - l;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d %d", &l[i], & r[i]);
}
getRMQ();
int ans = 0, tmp = 0;
for(int i = 1; i <= n; ++i) {
if(i == 1) {
int ll = RMQmax(2, n);
int rr = RMQmin(2, n);
tmp = getans(ll, rr);
ans = max(ans, tmp);
} else if(i == n) {
int ll = RMQmax(1, n - 1);
int rr = RMQmin(1, n - 1);
tmp = getans(ll, rr);
ans = max(ans, tmp);
} else {
int ll = max(RMQmax(1, i-1), RMQmax(i + 1, n));
int rr = min(RMQmin(1, i-1), RMQmin(i + 1, n));
ans = max(ans, getans(ll, rr));
}
}
printf("%d\n", ans);
return 0;
}
这题的hack数据卡常数,是真的坑爹。
做法很简单,看看数字中出现的数字的位数都有哪些。预处理出所有的数字 mod k m o d k 的值存进对应数字位数的map中,然后搞一搞余数就好了
#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
map <int, int> mp[15];
bool isocc[20];
int a[nmax];
int zeors[20];
int n, k;
int digits[nmax];
int main(){
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
digits[i] = log10(a[i]) + 1;
mp[digits[i]][a[i] % k] ++;
// isocc[digits[i]] = true;
}
ll ans = 0;
for(int i = 1; i <= n; ++i) {
ll tmp = a[i] % k;
mp[digits[i]][tmp] --;
for(int j = 1; j <= 10; ++j) {
tmp = (tmp * 10 ) % k;
if(mp[j].count((k - tmp % k) % k) > 0)
ans += mp[j][(k - tmp % k) % k];
// if(isocc[j])
}
mp[digits[i]][a[i] % k] ++;
}
printf("%I64d\n", ans);
return 0;
}
树形dp或者贪心。
#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 2e5 + 7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax], tot, ans;
bool iscover[nmax];
struct edge {
int to, nxt;
}e[nmax<<1];
void add_edge(int u, int v) {
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
int n;
void update(int u) {
for(int i = head[u]; i != -1; i = e[i].nxt) {
iscover[e[i].to] = true;
}
iscover[u] = true;
}
void dfs(int u, int f) {
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(v != f) {
dfs(v, u);
}
}
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(v != f && !iscover[v]) {
update(u);
ans ++;
}
}
}
int main() {
while (scanf("%d", &n) != EOF) {
memset(head, -1, sizeof(head));
// memset(iscover, 0 , sizeof iscover);
tot = ans = 0;
for(int i = 1; i <= n - 1; ++i) {
int u ,v;
scanf("%d %d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
update(1);
// iscover[1] = true;
for(int i = head[1]; i != -1; i = e[i].nxt) {
update(e[i].to);
}
dfs(1, -1);
printf("%d\n", ans);
}
return 0;
}