新的一年,又是改不完的bug和补不完的题,QAQ
做法:题意是在某个范围中使[l,r]区间数字变为0需要c[i]点能量,要问在k点能量的限制下,总和最大为多少。
大佬说用线段树加01背包,然而后来还是想错了,开始我在v数组上建了一棵线段树,后来发现在做01背包的时候会有重复,其实正解是在w数组上建线段树,后面再对两个数组进行01背包。
还有一个小技巧,最后要减的是最小的权值,所以取负号取最大,输出答案时dp[k]变号即可。
代码:
#include
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int N = 1e5+5;
LL T[4*N];
void update(int rt, int l, int r, int L, int R, LL x) {
if(l > R || L > r) return ;
if(L <= l && R >= r) {
T[rt] = min(T[rt], x);
return ;
}
int mid = l + r >> 1;
update(lson, L, R, x);
update(rson, L, R, x);
}
LL query(int rt, int l, int r, int pos) {
if(l == r) return T[rt];
int mid = l + r >> 1;
if(pos <= mid) return min(T[rt], query(lson, pos));
else return min(T[rt], query(rson, pos));
}
LL v[N];
LL dp[510], sum;
int main() {
memset(T, 0x3f, sizeof T);
LL n, k, m;
scanf("%lld%lld%lld", &n, &k, &m);
for(int i = 1; i <= n; ++i) {
scanf("%lld", &v[i]);
sum += v[i];
}
int l, r;
LL c;
for(int i = 1; i <= m; ++i) {
scanf("%d%d%lld", &l, &r, &c);
update(1, 1, n, l, r, c);
}
LL w;
for(int i = 1; i <= n; ++i) {
if(v[i] >= 0) continue;
w = query(1, 1, n, i);
v[i] = -v[i];
for(int j = k; j >= w; --j) {
dp[j] = max(dp[j], dp[j-w] + v[i]);
}
}
printf("%lld\n", sum + dp[k]);
return 0;
}
做法:二维数组用一维数组表示行和列,后面再输出行和列出现时间之间的最大值。
代码:
#include
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int N = 1e5+5;
int row[N], col[N]; //表示二维数组的行和列数组
int main() {
int n, m, t;
read(n); read(m); read(t);
int pos, num;
for(int i = 1; i <= t; ++i) {
read(pos); read(num);
if(pos == 1) row[num] = i;
else col[num] = i;
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
printf("%d ", max(row[i], col[j]));
}
puts("");
}
return 0;
}
做法:用找规律的方法
2 :
(1),(2) --> 12种
(1,2) --> 2种
3:
(1),(2),(3) --> 13种
(1,2),(1,3),(2,3) --> 2*2种
(1,2,3) --> 3种
易得
C n 1 + 2 ∗ C n 2 + 3 ∗ C n 3 + . . . + n ∗ C n n = n ∗ 2 n − 1 C_n^1 + 2 * C_n^2 + 3 * C_n^3 + ... + n * C_n^n = n * 2 ^{n-1} Cn1+2∗Cn2+3∗Cn3+...+n∗Cnn=n∗2n−1
代码:
#include
using namespace std;
typedef long long LL;
const LL Mod = 1e9+7;
LL ksm(LL a, LL n) {
LL sum = 1;
while(n) {
if(n & 1) sum = sum * a % Mod;
a = a * a % Mod;
n >>= 1;
}
return sum;
}
int main () {
LL n;
cin >> n;
cout << n * ksm(2, n-1) % Mod << endl;
return 0;
}
做法:对端点进行贪心判断,欸,最后还是找不到bug看了大佬的代码…
代码:
#include
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int N = 1e5+5;
struct xx {
int l, r;
bool operator < (const xx &c) const {
if(l != c.l) return l < c.l;
return r < c.r;
}
}ap[N];
int main() {
int n, m;
read(n); read(m);
for(int i = 1; i <= m; ++i) {
read(ap[i].l); read(ap[i].r);
}
sort(ap+1, ap+m+1);
int ans = 0, L = 0, R = 0;
for(int i = 1; i <= m; ++i) {
if(R > ap[i].l) R = max(R, ap[i].r);
else if(R < ap[i].l) {
ans = max(ans, ap[i].l - L);
L = R + 1; R = ap[i].r;
}
}
printf("%d\n", max(ans, n-R));
return 0;
}