SCP(大雾)复习板子?
唔
复习一下各种板子?
- 树状数组
其实忘得差不多了,只会lowbit了qaq
树状数组一的话就正常搞
#include<cstdio>
#define sev en
using namespace std;
#define N 500010
int n,m;
int tree[N];
int lowbit(int x) {
return x & (-x);
}
void add(int x,int k) {
while(x <= n) {
tree[x] += k;
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
int x;
scanf("%d",&x);
add(i,x);
}
for(int i = 1; i <= m; i++) {
int op,x,k;
scanf("%d%d%d",&op,&x,&k);
if(op == 1)
add(x,k);
else
printf("%d\n",query(k) - query(x - 1));
}
return 0;
}
树状数组二用到了差分
反正是忘了嘤
#include<cstdio>
#define sev en
using namespace std;
#define N 500010
int n,m;
int tree[N];
int lowbit(int x) {
return x & (-x);
}
void add(int x,int k) {
while(x <= n) {
tree[x] += k;
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
int st = 0;
for(int i = 1; i <= n; i++) {
int x;
scanf("%d",&x);
add(i,x - st);
st = x;
}
for(int i = 1; i <= m; i++) {
int op,x,y,k;
scanf("%d",&op);
if(op == 1) {
scanf("%d%d%d",&x,&y,&k);
add(x,k);
add(y + 1,-k);
} else {
scanf("%d",&x);
printf("%d\n",query(x));
}
}
return 0;
}
- 并查集
第一遍居然写跪了
(我码之前还表示这要是不会就告辞了 脸疼
无论如何反正码风比以前好看了
#include<cstdio>
#define sev en
using namespace std;
#define N 10010
int n,m;
int fa[N];
int get(int x) {
if(fa[x] == x)
return x;
return fa[x] = get(fa[x]);
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
fa[i] = i;
for(int i = 1; i <= m; i++) {
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op == 1)
fa[get(x)] = get(y);
else {
if(get(x) == get(y))
printf("Y\n");
else
printf("N\n");
}
}
return 0;
}
- 线段树
前一阵子刚码过一遍
但仍然出了一些问题
比如需要记住lazy乘16 询问的时候往下传是+= sum也是w
说实在的
现在心情有点差 特别差那种 有点想离开
真是无趣啊 千篇一律的人生 碌碌无为的时光 蝇营狗苟的未来 浑浑噩噩的打转
真烦
#include<cstdio>
#define sev en
using namespace std;
#define N 100010
int n,m;
long long sum[N << 2],lazy[N << 4];
int l[N << 2],r[N << 2];
void build(int now,int L,int R) {
lazy[now] = 0;
l[now] = L,r[now] = R;
if(L == R) {
scanf("%lld",&sum[now]);
return ;
}
int mid = (L + R) >> 1;
build(now << 1,L,mid);
build(now << 1 | 1,mid + 1,R);
sum[now] = sum[now << 1] + sum[now << 1 | 1];
}
void modify(int now,int L,int R,int k) {
if(L == l[now] && R == r[now]) {
lazy[now] += k;
return ;
}
sum[now] += (R - L + 1) * k;
int mid = (l[now] + r[now]) >> 1;
if(mid >= R)
modify(now << 1,L,R,k);
else if(L > mid)
modify(now << 1 | 1,L,R,k);
else {
modify(now << 1,L,mid,k);
modify(now << 1 | 1,mid + 1,R,k);
}
return ;
}
long long query(int now,int L,int R) {
sum[now] += (r[now] - l[now] + 1) * lazy[now];
lazy[now << 1] += lazy[now],lazy[now << 1 | 1] += lazy[now];
lazy[now] = 0;
if(L == l[now] && R == r[now])
return sum[now];
int mid = (l[now] + r[now]) >> 1;
if(mid >= R)
return query(now << 1,L,R);
else if(L > mid)
return query(now << 1 | 1,L,R);
else
return query(now << 1,L,mid) + query(now << 1 | 1,mid + 1,R);
}
int main() {
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i = 1; i <= m; i++) {
int op,x,y,k;
scanf("%d",&op);
if(op == 1) {
scanf("%d%d%d",&x,&y,&k);
modify(1,x,y,k);
} else {
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,x,y));
}
}
return 0;
}
- 最短路-dijkstra
唔,虽然有点问题 但码的还算可以
为了优化加的vis别忘了就好w
(没加的时候标准版过不了嘤
心情不要太差哦
你看 你的私信里有一个明亮的1呢
#include<cstdio>
#include<queue>
#define sev en
using namespace std;
#define N 500010
#define INF 2147483647
int n,m,s,cnt;
int to[N],nxt[N],w[N],head[N];
int dis[N],vis[N];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void add(int x,int y,int z){
to[++cnt] = y;
w[cnt] = z;
nxt[cnt] = head[x];
head[x] = cnt;
}
int main(){
scanf("%d%d%d",&n,&m,&s);
for(int i = 1;i <= m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
for(int i = 1;i <= n;i++)
dis[i] = INF;
dis[s] = 0;
q.push(make_pair(0,s));
while(!q.empty()){
int x = q.top().second;
q.pop();
if(vis[x])
continue;
vis[x] = 1;
for(int i = head[x];i;i = nxt[i]){
int v = to[i];
if(dis[x] != INF && dis[v] > dis[x] + w[i]){
dis[v] = dis[x] + w[i];
q.push(make_pair(dis[v],v));
}
}
}
for(int i = 1;i <= n;i++)
printf("%d ",dis[i]);
return 0;
}
- 最小生成树-kruskal
难得的一边写过的代码
有点困有点累好闷啊要死了
#include<cstdio>
#include<algorithm>
#define sev en
using namespace std;
#define M 200010
#define N 5010
int n,m;
struct EDGE{
int x,y,w;
bool operator <(const EDGE &a)const{
return w < a.w;
}
}e[M << 1];
int fa[N],ans,num;
int get(int x){
if(fa[x] == x)
return x;
return fa[x] = get(fa[x]);
}
void kruskal(){
for(int i = 1;i <= m;i++){
int l = get(e[i].x),r = get(e[i].y);
if(l != r){
fa[l] = r;
ans += e[i].w;
num++;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
sort(e + 1,e + m + 1);
for(int i = 1;i <= n;i++)
fa[i] = i;
kruskal();
if(num < n - 1)
printf("orz");
else
printf("%d",ans);
return 0;
}
- 逆序对
重新写了一下逆序对 代码跟之前的有一点点不同
大概码风不太一样?更好了?更符合我现在的审美吧
树状数组
#include<cstdio>
#include<algorithm>
#define sev en
using namespace std;
#define N 500010
int n;
int a[N],b[N];
long long ans,tree[N];
int lowbit(int x){
return x & (-x);
}
void add(int x){
while(x <= n){
tree[x]++;
x += lowbit(x);
}
}
long long query(int x){
long long ret = 0;
while(x){
ret += tree[x];
x -= lowbit(x);
}
return ret;
}
int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
b[i] = a[i];
}
sort(a + 1,a + n + 1);
int num = unique(a + 1,a + n + 1) - a - 1;
for(int i = 1; i <= n; i++)
b[i] = lower_bound(a + 1,a + num + 1,b[i]) - a;
for(int i = n; i >= 1; i--) {
add(b[i]);
ans += query(b[i] - 1);
}
printf("%lld",ans);
return 0;
}
归并排序
#include<cstdio>
#define sev en
using namespace std;
#define N 500010
int n;
int a[N],q[N];
long long ans;
void merge(int l,int r) {
if(l == r)
return ;
int mid = (l + r) >> 1;
merge(l,mid);
merge(mid + 1,r);
int i = l,j = mid + 1,k = l;
while(i <= mid && j <= r) {
if(a[i] <= a[j])
q[k++] = a[i++];
else {
q[k++] = a[j++];
ans += (mid - i + 1);
}
}
while(i <= mid)
q[k++] = a[i++];
while(j <= r)
q[k++] = a[j++];
for(int i = l; i <= r; i++)
a[i] = q[i];
}
int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
merge(1,n);
printf("%lld",ans);
return 0;
}
- 素数筛法
先写了个素数个数emmm
纯筛 没用啥筛法 硬刚就好
#include<cstdio> #include<cmath> #define sev en using namespace std; const int N = 1e8 + 10; bool f[N]; int main() { int n; scanf("%d",&n); int ans = n - 1; for(int i = 2; i <= sqrt(n); i++) { if(f[i]) continue; for(int j = i * 2; j <=n; j += i) if(!f[j]) f[j] = 1,ans--; } printf("%d",ans); return 0; }
然后写了个线性筛素数
欧拉筛
一开始写prime数组写到判断是否素数后面了 所以是bool类型 de了5分钟 气死
emmmm也不清楚到底懂得彻不彻底
希望能记住吧~
#include<cstdio> #include<cstring> #define sev en using namespace std; const int N = 1e7 + 10; int n,m; bool f[N]; int prime[N]; int num; void Prime() { memset(f,true,sizeof(f)); f[0] = f[1] = 0; for(int i = 2; i <= n; i++) { if(f[i]) { prime[num++] = i; } for(int j = 0; j < num && i * prime[j] <= n; j++) { f[i * prime[j]] = 0; if(!(i % prime[j])) break; } } return ; } int main() { scanf("%d%d",&n,&m); Prime(); while(m--) { int x; scanf("%d",&x); if(f[x]) printf("Yes\n"); else printf("No\n"); } return 0; }