HNOI2018做题笔记
HNOI2018
寻宝游戏(位运算、基数排序)
看到位运算就要按位考虑。二进制下,\(\land 1\)与\(\lor 0\)没有意义的,\(\land 0\)强制这一位变为\(0\),\(\lor 1\)强制这一位变为\(1\)
那么如果某一位的答案要为\(0\),也就意味着:要么同时不存在\(\land 0\)与\(\lor 1\),要么最后一个\(\land 0\)后面不能有\(\lor 1\)。答案为\(1\)同理。
那么对于每一位,将所有\(a_i\)在这一位上的值从右往左看作一个二进制数\(x\),将操作序列\(\land\)对应为\(1\)、\(\lor\)对应为\(0\),从右往左看作一个二进制数\(op\),那么如果答案的这一位为\(0\),必须满足\(op \geq x\)。反之则要满足\(op < x\)。
那么最后的答案就会表现为\(a \leq op < b\)的形式,答案为\(\min\{b-a , 0\}\)。
那么将\(x\)排序,每一次扫一遍找到\(a\)和\(b\)就可以了。注意到给出这\(m\)个数的顺序正好是从低位到高位依次给出,所以可以基数排序。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
//This code is written by Itst
using namespace std;
const int MOD = 1e9 + 7;
int srt[5007] , val[5007] , tmp[5007] , pot[3];
int N , M , Q;
char s[5007];
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
scanf("%d %d %d" , &N , &M , &Q);
for(int i = 1 ; i <= M ; ++i)
srt[i] = i;
int times = 1;
for(int i = 1 ; i <= N ; ++i){
pot[0] = pot[1] = 0;
scanf("%s" , s + 1);
for(int j = 1 ; j <= M ; ++j){
++pot[s[j] - 47];
if(s[j] - 48)
val[j] = (val[j] + times) % MOD;
}
for(int j = 1 ; j <= M ; ++j)
tmp[++pot[s[srt[j]] - 48]] = srt[j];
memcpy(srt , tmp , sizeof(tmp));
times = times * 2 % MOD;
}
srt[M + 1] = M + 1;
val[M + 1] = times;
while(Q--){
scanf("%s" , s + 1);
int L = 0 , R = M + 1;
for(int i = 1 ; i <= M ; ++i)
if(s[srt[i]] == '1'){
R = i;
break;
}
for(int i = M ; i ; --i)
if(s[srt[i]] == '0'){
L = i;
break;
}
if(L > R)
puts("0");
else
printf("%d\n" , (val[srt[R]] - val[srt[L]] + MOD) % MOD);
}
return 0;
}
转盘(线段树、单调栈)
毫无疑问要断环成链,那么我们要求的就是\(\min\limits_{i=1}^N\{ \max\limits_{j=0}^{N - 1} \{ a_{j+i} + (N - 1 - j)\} \}\),即\(\min\limits_{i=1}^N \{\max\limits_{j=i}^{N+i-1}\{ a_{j} - j \} + i \} + N - 1\)
所以要算\(\min\limits_{i=1}^N \{\max\limits_{j=i}^{N+i-1}\{ a_{j} - j \} + i \}\)。因为\(a_j - j > a_{j+N} - (j+N)\),所以原式等于\(\min\limits_{i=1}^N \{\max\limits_{j=i}^{2N}\{ a_{j} - j \} + i \}\)。如果\(a_j - j\)有贡献,它一定是后缀最大值,而所有后缀最大值构成的是一个单调栈。对于单调栈中的第\(k\)个元素的位置\(L_k\),我们要求\(\min\limits_{i=L_{k-1} + 1}^N \{ a_{L_k} - L_k + i \}\),显然\(i = L_{k-1}+1\)时有最小值。
所以如果只有\(1\)次询问,可以维护一个单调栈,对于栈内每一个元素找到它之前的最后一个比它大的元素的位置,\(+1\)之后就是它能取到的区间中最左的左端点。
然后考虑修改。不难想到使用线段树维护单调栈(基础实现见楼房重建)
对于线段树上每一个点维护单调栈的最大值和答案。线段树上每一个点维护的答案是:对于左儿子传上来的单调栈\(L_1,L_2,...,L_k\),左端点为\(L_1+1,L_2+1,...,L_k+1\)的区间的答案。
每一次合并左右儿子时,因为右半部分一定会是当前单调栈的一部分,所以拿右儿子的最大值\(max\)放在左儿子上二分得到左儿子传上来的单调栈。
如果当前节点的右儿子的最大值\(> max\),意味着当前点维护的单调栈的左儿子传上来的部分一定也是现在正在寻找的栈的一部分,直接把答案拿过来然后递归右儿子,否则递归左儿子。到叶子节点意味着找到了\(L_k\),记得计算一次左端点为\(L_k+1\)时的答案。
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cctype>
#include<algorithm>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
while(!isdigit(c))
c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
}
const int MAXN = 1e5 + 7;
struct node{
int rgL , rgR , maxN , ans;
}Tree[MAXN << 3];
int val[MAXN << 1] , N , M , P;
#define lch (x << 1)
#define rch (x << 1 | 1)
#define mid ((l + r) >> 1)
#define PII pair < int , int >
int find(int x , int dir){
if(Tree[x].rgL == Tree[x].rgR)
return Tree[x].rgL + dir + 1;
if(Tree[rch].maxN > dir)
return min(Tree[x].ans , find(rch , dir));
return find(lch , dir);
}
inline void pushup(int x){
Tree[x].maxN = max(Tree[rch].maxN , Tree[lch].maxN);
Tree[x].ans = find(lch , Tree[rch].maxN);
}
void init(int x , int l , int r){
Tree[x].rgL = l;
Tree[x].rgR = r;
Tree[x].ans = 0x7fffffff;
if(l == r)
Tree[x].maxN = val[l] - l;
else{
init(lch , l , mid);
init(rch , mid + 1 , r);
pushup(x);
}
}
void modify(int x , int l , int r , int tar){
if(l == r){
Tree[x].maxN = val[tar] - tar;
return;
}
if(mid >= tar)
modify(lch , l , mid , tar);
else
modify(rch , mid + 1 , r , tar);
pushup(x);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read(); M = read(); P = read();
for(int i = 1 ; i <= N ; ++i)
val[i] = val[i + N] = read();
init(1 , 1 , N << 1);
int lastans = Tree[1].ans + N - 1;
cout << lastans << '\n';
for(int i = 1 ; i <= M ; ++i){
int x = P ? read() ^ lastans : read() , y = P ? read() ^ lastans : read();
val[x] = val[x + N] = y;
modify(1 , 1 , N << 1 , x);
modify(1 , 1 , N << 1 , x + N);
cout << (lastans = Tree[1].ans + N - 1) << '\n';
}
return 0;
}
毒瘤(虚树)
如果\(m=n-1\)就是简单的树的独立集个数统计问题,直接树形DP即可;但是相比于树上独立集,这里多了\(11\)条约束。
注意到\(11\)比较小,可以暴力枚举。对于每一条边的两个端点有\((0,1),(0,0),(1,0)\)(\(1\)表示选,\(0\)表示不选)三种情况,而\((0,0),(0,1)\)两种情况可以合成一种,即只确定其中一端不选,另一端不做限制。所以一条边只有两种情况,所以可以\(2^{11}\)地枚举每条边的状态,每一次都在树上DP求一遍独立集个数。
考虑如何优化。注意到每一次只有\(22\)个点的状态会发生变化,故将这\(22\)个点拿出来建立虚树。对于虚树上的每一条边求出其转移系数。求转移系数的方式就是在原树上暴跳父亲,每一次把没有关键点的子树直接拿过来合并。求转移系数对应下面代码里的calc函数部分
#include<iostream>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
while(!isdigit(c))
c = getchar();
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return a;
}
const int MAXN = 1e5 + 13 , MOD = 998244353;
struct Edge{
int end , upEd;
}Ed[MAXN << 1];
int head[MAXN] , DP[MAXN][2] , dep[MAXN] , dfn[MAXN] , jmp[MAXN][19];
int N , M , cntEd = 1 , cnt , ts , mr[21];
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
#define go(a , b , c) (a = 1ll * a * (b + c) % MOD)
void dfs(int x , int p){
dep[x] = dep[p] + 1;
dfn[x] = ++ts;
jmp[x][0] = p;
for(int i = 1 ; i <= 16 ; ++i)
jmp[x][i] = jmp[jmp[x][i - 1]][i - 1];
DP[x][0] = DP[x][1] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p)
if(!dep[Ed[i].end]){
dfs(Ed[i].end , x);
go(DP[x][0] , DP[Ed[i].end][0] , DP[Ed[i].end][1]);
DP[x][1] = 1ll * DP[x][1] * DP[Ed[i].end][0] % MOD;
}
else
if(dep[Ed[i].end] > dep[x])
mr[++cnt] = i;
}
bool cmp(int a , int b) {return dfn[a] < dfn[b];}
inline int LCA(int x , int y){
if(dep[x] < dep[y])
x ^= y ^= x ^= y;
for(int i = 16 ; i >= 0 ; --i)
if(dep[x] - (1 << i) >= dep[y])
x = jmp[x][i];
if(x == y)
return x;
for(int i = 16 ; i >= 0 ; --i)
if(jmp[x][i] != jmp[y][i]){
x = jmp[x][i];
y = jmp[y][i];
}
return jmp[x][0];
}
#define pb push_back
#define add(a , b) (a + b >= MOD ? a + b - MOD : a + b)
vector < int > ch[MAXN] , nd;
int dp[MAXN][2] , xs[MAXN][2][2] , st[101] , top , cntN;
bool mrk[MAXN];
void calc(int x){
xs[x][0][0] = xs[x][1][1] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!mrk[Ed[i].end] && jmp[Ed[i].end][0] == x){
go(xs[x][0][0] , DP[Ed[i].end][1] , DP[Ed[i].end][0]);
xs[x][1][1] = 1ll * xs[x][1][1] * DP[Ed[i].end][0] % MOD;
}
int p = x;
while(!mrk[jmp[p][0]] && jmp[p][0]){
mrk[p = jmp[p][0]] = 1;
int P = xs[x][0][0] , Q = xs[x][0][1];
xs[x][0][0] = add(P , xs[x][1][0]);
xs[x][0][1] = add(Q , xs[x][1][1]);
xs[x][1][0] = P;
xs[x][1][1] = Q;
for(int i = head[p] ; i ; i = Ed[i].upEd)
if(jmp[Ed[i].end][0] == p && !mrk[Ed[i].end]){
go(xs[x][0][0] , DP[Ed[i].end][1] , DP[Ed[i].end][0]);
go(xs[x][0][1] , DP[Ed[i].end][1] , DP[Ed[i].end][0]);
xs[x][1][0] = 1ll * xs[x][1][0] * DP[Ed[i].end][0] % MOD;
xs[x][1][1] = 1ll * xs[x][1][1] * DP[Ed[i].end][0] % MOD;
}
}
}
void DFS(int x){
mrk[x] = 1;
for(int i = 0 ; i < ch[x].size() ; ++i)
DFS(ch[x][i]);
calc(x);
}
void init(){
nd.pb(1);
for(int i = 1 ; i <= cnt ; ++i){
nd.pb(Ed[mr[i]].end);
nd.pb(Ed[mr[i] ^ 1].end);
}
sort(nd.begin() , nd.end() , cmp);
cntN = unique(nd.begin() , nd.end()) - nd.begin();
for(int i = 0 ; i < cntN ; ++i){
if(top){
int t = LCA(st[top] , nd[i]);
while(top - 1 && dep[t] <= dep[st[top - 1]]){
ch[st[top - 1]].pb(st[top]);
--top;
}
if(dep[t] < dep[st[top]]){
ch[t].pb(st[top]);
st[top] = t;
}
}
st[++top] = nd[i];
}
while(top - 1){
ch[st[top - 1]].pb(st[top]);
--top;
}
DFS(1);
}
int sum , zt[MAXN];
void getans(int x){
dp[x][0] = zt[x] == 0 || zt[x] == 1;
dp[x][1] = zt[x] == 0 || zt[x] == 2;
for(int i = 0 ; i < ch[x].size() ; ++i){
getans(ch[x][i]);
go(dp[x][0] , dp[ch[x][i]][0] , dp[ch[x][i]][1]);
dp[x][1] = 1ll * dp[x][1] * dp[ch[x][i]][0] % MOD;
dp[ch[x][i]][0] = dp[ch[x][i]][1] = 0;
}
int p = dp[x][0] , q = dp[x][1];
dp[x][0] = (1ll * xs[x][0][0] * p + 1ll * xs[x][0][1] * q) % MOD;
dp[x][1] = (1ll * xs[x][1][0] * p + 1ll * xs[x][1][1] * q) % MOD;
}
void Dfs(int x){
if(x > cnt){
getans(1);
sum = (0ll + sum + dp[1][0] + dp[1][1]) % MOD;
dp[1][0] = dp[1][1] = 0;
return;
}
int l = Ed[mr[x]].end , r = Ed[mr[x] ^ 1].end , p = zt[l] , q = zt[r];
if((p == 0 || p == 1) && (q == 0 || q == 2)){
zt[l] = 1; zt[r] = 2;
Dfs(x + 1);
zt[l] = p; zt[r] = q;
}
if(q == 0 || q == 1){
zt[r] = 1;
Dfs(x + 1);
zt[r] = q;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read();
M = read();
for(int i = 1 ; i <= M ; ++i){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
dfs(1 , 0);
init();
Dfs(1);
cout << sum;
return 0;
}
游戏(拓扑排序)
不难想到对于一段中间的门都不需要钥匙的区间缩成一个点,然后预处理每一个点能够到达的左右端点
暴力的思路是每一次暴力向左右拓展
但可以知道:对于门\((x,y)\),如果\(y \leq x\),那么一定是从\(x\)所在区间通过这扇门走向\(x+1\)所在区间,反之亦然。那么若左边的某个区间能够通过这扇门,它一定能够到达\(x+1\)所在区间能够到达的所有区间。所以连边\((x,x+1)\)表示要先拓展\(x+1\),后拓展\(x\)。然后拓扑排序决定拓展顺序,一个个拓展就可以过了。复杂度似乎是线性的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
#include<cassert>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 1e6 + 7;
vector < int > door , ch[MAXN];
int lft[MAXN] , rht[MAXN] , L[MAXN] , R[MAXN] , in[MAXN];
int N , M;
inline void add(int x , int y){
++in[y];
ch[x].push_back(y);
}
queue < int > q , work;
void TopSort(){
for(int i = 1 ; i <= M ; ++i)
if(!in[i])
q.push(i);
while(!q.empty()){
int t = q.front();
q.pop();
work.push(t);
for(int i = 0 ; i < ch[t].size() ; ++i)
if(!--in[ch[t][i]])
q.push(ch[t][i]);
}
}
inline int find(int x){
return lower_bound(door.begin() , door.end() , x) - door.begin();
}
inline void calc(int x){
while(L[x] != 1 || door[R[x]] != N){
if(L[x] != 1 && rht[door[L[x] - 1] + 1] && rht[door[L[x] - 1] + 1] <= door[R[x]]){
L[x] = L[L[x] - 1];
continue;
}
if(door[R[x]] != N && lft[door[R[x]]] >= door[L[x] - 1] + 1){
R[x] = R[R[x] + 1];
continue;
}
break;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
N = read();
M = read();
int Q = read();
for(int i = 1 ; i <= M ; ++i){
int x = read() , y = read();
y <= x ? lft[x] = y : rht[x + 1] = y;
door.push_back(x);
}
++M;
door.push_back(0);
door.push_back(N);
sort(door.begin() , door.end());
for(int i = 1 ; i <= M ; ++i){
L[i] = R[i] = i;
if(rht[door[i - 1] + 1])
add(i - 1 , i);
if(lft[door[i]])
add(i + 1 , i);
}
TopSort();
while(!work.empty()){
calc(work.front());
work.pop();
}
while(Q--){
int l = find(read()) , r = read();
puts(door[L[l] - 1] + 1 <= r && door[R[l]] >= r ? "YES" : "NO");
}
return 0;
}
排列(贪心、并查集)
首先考虑合法排列的限制条件,也就是在排列\(p\)中,对于\(\forall i \in [1,N]\) , \(a_i\)要出现在\(i\)的前面。我们连边\((i,a_i)\),表示\(i\)要在\(a_i\)之后出现。如果存在合法的排列,最后连成的一定是一棵树。
接下来考虑求最大值。有一种比较naive的贪心:每一次都选择当前可以选择的点中最小的。这种贪心策略显然是错的,反例也很好举。
但这似乎能给我们一些启发:对于当前所有点权中最小的数,它一定会在它的父亲被选完之后立即选。那么考虑将它和它的父亲缩成一个点,表示这两个点的选择是连续的。
那么接下来的问题就是缩成的这个点的权值是多少。
不妨设当前所有点权中最小点权对应的点权为\(x\),它的父亲权为\(y\),有另一个点权为\(z\),并且满足\(y\)对应的点和\(z\)对应的点现在都可以选。那么现在有两种决策:1、先选\(y,x\),后选\(z\),权值和为\(y+2x+3z\);2、先选\(z\),后选\(y,x\),权值和为\(z+2y+3x\)
我们需要取更优的,所以只需要比较它们的大小,故同时减去\(x-z\),除以\(2\),那么第一种方案权值为\(\frac{x+y}{2}+2z\),第二种方案权值为\(z + 2\frac{x+y}{2}\)
可以发现之前的两个点\(x,y\)在这个时候可以等价为一个点权为\(\frac{x+y}{2}\)的点。根据这个思路可以得到点权为\(\frac{\text{它所包含的点的点权和}}{\text{它所包含的点的个数}}\)。
那么可以得到一个贪心:每一次选择一个点权最小的点,把它和它父亲合并,可以使用并查集维护合并过程。最后把合并的点拆开计算答案。
#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c)){
if(c == '-')
f = 1;
c = getchar();
}
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 5e5 + 10;
struct Edge{
int end , upEd;
}Ed[MAXN << 1];
int head[MAXN] , pre[MAXN << 1] , fa[MAXN << 1] , ch[MAXN << 1][2] , size[MAXN << 1] , cntEd , cntNode , N , t;
long long pri[MAXN << 1] , ans;
bool vis[MAXN] , mark[MAXN << 1];
struct cmp{
bool operator ()(int a , int b){
return pri[a] * size[b] > pri[b] * size[a];
}
};
priority_queue < int , vector < int > , cmp > q;
int find(int x){
return fa[x] == x ? x : (fa[x] = find(fa[x]));
}
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
bool dfs(int x , int p){
pre[x] = p;
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p)
if(vis[Ed[i].end] || dfs(Ed[i].end , x))
return 1;
return 0;
}
void color(int x){
if(x <= N)
ans += t++ * pri[x];
else{
color(ch[x][0]);
color(ch[x][1]);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
cntNode = N = read();
size[0] = 1;
for(int i = 1 ; i <= N ; ++i){
int a = read();
addEd(a , i);
addEd(i , a);
fa[i] = i;
size[i] = 1;
}
for(int i = 1 ; i <= N ; ++i){
pri[i] = read();
q.push(i);
}
for(int i = 0 ; i <= N ; ++i)
if(!vis[i])
if(dfs(i , -1)){
puts("-1");
return 0;
}
while(!q.empty()){
int t = q.top();
q.pop();
if(mark[t])
continue;
int f = find(pre[t]) , x = ++cntNode;
fa[f] = fa[t] = fa[x] = x;
size[x] = size[f] + size[t];
pri[x] = pri[f] + pri[t];
ch[x][0] = f;
ch[x][1] = t;
pre[x] = pre[f];
mark[t] = mark[f] = 1;
if(pre[x] != -1)
q.push(x);
}
color(cntNode);
cout << ans;
return 0;
}
道路(树形DP)
设\(f_{i,j,k}\)表示从\(1\)号点到\(i\)号点经过了\(j\)条公路、\(k\)条铁路时,\(i\)及其子树的最小不便利值和,从底往上DP,转移枚举修哪一条边。
#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
bool f = 0;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = 1;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 20010;
long long dp[1010][41][41] , num[MAXN][3];
int ch[MAXN][2] , headSt , N;
void dfs(int now){
++headSt;
if(now < 0){
now = -now;
for(int i = 0 ; i <= 40 ; ++i)
for(int j = 0 ; j <= 40 ; ++j)
dp[headSt][i][j] = (num[now][0] + i) * (num[now][1] + j) * num[now][2];
return;
}
dfs(ch[now][0]);
dfs(ch[now][1]);
for(int i = 0 ; i < 40 ; ++i)
for(int j = 0 ; j < 40 ; ++j)
dp[headSt - 2][i][j] = min(dp[headSt - 1][i + 1][j] + dp[headSt][i][j] , dp[headSt - 1][i][j] + dp[headSt][i][j + 1]);
headSt -= 2;
}
int main(){
N = read();
for(int i = 1 ; i < N ; i++){
ch[i][0] = read();
ch[i][1] = read();
}
for(int i = 1 ; i <= N ; i++){
num[i][0] = read();
num[i][1] = read();
num[i][2] = read();
}
dfs(1);
cout << dp[1][0][0];
return 0;
}
HNOI2018做题笔记的更多相关文章
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
- C语言程序设计做题笔记之C语言基础知识(上)
C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...
- SDOI2017 R1做题笔记
SDOI2017 R1做题笔记 梦想还是要有的,万一哪天就做完了呢? 也就是说现在还没做完. 哈哈哈我竟然做完了-2019.3.29 20:30
- SDOI2014 R1做题笔记
SDOI2014 R1做题笔记 经过很久很久的时间,shzr又做完了SDOI2014一轮的题目. 但是我不想写做题笔记(
- SDOI2016 R1做题笔记
SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...
- LCT做题笔记
最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...
- java做题笔记
java做题笔记 1. 初始化过程是这样的: 1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化: 2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序 ...
- SAM 做题笔记(各种技巧,持续更新,SA)
SAM 感性瞎扯. 这里是 SAM 做题笔记. 本来是在一篇随笔里面,然后 Latex 太多加载不过来就分成了两篇. 标 * 的是推荐一做的题目. trick 是我总结的技巧. I. P3804 [模 ...
- PKUWC/SC 做题笔记
去年不知道干了些啥,什么省选/营题都没做. 现在赶应该还来得及(?) 「PKUWC2018」Minimax Done 2019.12.04 9:38:55 线段树合并船新玩法??? \(O(n^2)\ ...
随机推荐
- IE9获取file控件的本地文件路径
最近发现,在IE9下,公司网站的本地图片预览都无法正常显示,经过测试发现,原因在于IE9下无法获取file控件的文件路径. 以前的代码如下: var strPic = fileImg.value; i ...
- 转载---解决 eclipse 中发布的java-web工程,jar包无法发布到tomcat 的lib下。
1.首先: Server Locations修改后会变灰,如果需要更改设置,则需要移除与Tomcat服务器关联的项目,同时,鼠标右键菜单Clean清除Tomcat服务器的状态^^就可以修改了. 此时E ...
- Java并发编程(四)synchronized
一.synchronized同步方法或者同步块 在了解synchronized关键字的使用方法之前,我们先来看一个概念:互斥锁,顾名思义:能到达到互斥访问目的的锁. 举个简单的例子:如果对临界资源加上 ...
- maven(九),install安装到本地仓库
下载oracle驱动jar包 在maven中央仓库中,是没有oracle驱动jar包的.因为oracle是商业软件,其jar包不允许用作开源用途.从http://www.mvnrepository.c ...
- 03-14_WLST配置现有的Domain
本文重点: WLST在线模式配置现有的domains. WLST离线模式配置现有的domains. 1.WLST在线模式配置现有的domains 由于和一个活动的domain进行交互, ...
- 安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details"错误.原因是启动"VisualSVN Server"失败
安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server ...
- php开发中遇到的一些问题
php警告提示A session had already been started – ignoring session_start() 解决方案 判断 如果session_id 不存在,说明没有储存 ...
- python 计时累积超过24小时时继续往上累加
最近在做一个工具,要求在工具上面加上程序运行的时间,所以做了个计时器 在网上找了很多发现都是24小时制的,超过24小时后就会回0 然后自己根据24小时制修改了一个不停累加时间的 若是想超过24小时后以 ...
- Linux 小知识翻译 - 「桌面环境」
这次聊聊桌面环境. 上次聊了 X Window System 相关的内容,虽然令人意外,但X Window System 和桌面环境不是一回事.请大家稍微考虑一下. X Window System 是 ...
- [BZOJ 3829][POI2014] FarmCraft
先贴一波题面... 3829: [Poi2014]FarmCraft Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 421 Solved: 197[ ...