1、快速读入
ll read(){
ll ret = 0;bool fl = 0;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') fl = 1;ch = getchar();}
while(ch >= '0' && ch <= '9') ret = ret * 10 + ch - '0', ch = getchar();
return fl ? -ret : ret;
}
2、java大整数
import java.util.*;
//import com.sun.xml.internal.ws.api.server.AbstractServerAsyncTransport;
import java.math.*;
public class Main{
public static void main(String args[]){
Scanner cin = new Scanner(System.in);
String str1, str2;
String a;
BigDecimal A, B;
double b;
while(cin.hasNext()) {
str1 = cin.next();
if(str1.charAt(0) == '1') {
System.out.println(str1 + " [8] = " + "1" + " [10]");
continue;
}
str2 = str1.substring(2, str1.length());
//System.out.println(str2);
BigInteger c = new BigInteger(str2, 8);
a = c.toString(10);
A = new BigDecimal(a);
for(int i = 0; i < str2.length(); i++) {
A = A.divide(BigDecimal.valueOf(8));
}
System.out.println(str1 + " [8] = " + A + " [10]");
}
}
}
3、线性筛
void Prime(){
for(int i = 2; i <= n; i++)
isprime[i] = 1;
for(int i = 2; i <= n; i++){
if(isprime[i]) prime[++cnt] = i, phi[i] = i - 1;
for(int j = 1; j <= cnt && prime[j] * i <= n; j++){
isprime[prime[j] * i] = 0;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
4、扩展欧几里得
void exgcd(ll a, ll b, ll &d, ll &x, ll &y) {
if(!b) {d = a; x = 1; y = 0; return;}
exgcd(b, a % b, d, y, x); y -= x * (a / b);
}
5、中国剩余定理
(普通)
……留坑
(扩展)
ll excrt() {
ll M = m[1], R = r[1], d, x, y;
for(int i = 2; i <= n; i++) {
exgcd(M, m[i], d, x, y);
if((R - r[i]) % d) return -1;
x = (R - r[i]) / d * x % m[i];
R -= M * x;
M = M * m[i] / d;
R %= M;
}
return (R % M + M) % M;
}
6、BM算法
#include
#include
#include
#include
#include
#include
#include
7、莫比乌斯反演
#include
#include
#define N 100005
#define ll long long
using namespace std;
bool p[N]={1,1};
int prime[N],mu[N],sum[N],cnt,t,a,b,c,d,k;
void getmu(){
mu[1]=1; cnt=0;
for(int i = 2; i < N; i++){
if(!p[i]){
prime[++cnt]=i;
mu[i]=-1;
}
for(int j = 1; j <= cnt && i * prime[j] < N; j++){
p[i * prime[j]] = 1;
if(i % prime[j] == 0){
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i < N; i++) sum[i] = sum[i-1] + mu[i];
//for(int i=1;i<100;i++) printf("%d\n",mu[i]);
}
ll getans(int n,int m){
ll ret = 0;
if(n > m) swap(n, m);
for(int i = 1, last; i <= n; i = last + 1){
last = min(n / (n / i), m / (m / i));
ret += (ll)(n / i) * (ll)(m / i)*(ll)(sum[last] - sum[i-1]);
}
return ret;
}
int main(){
scanf("%d", &t);
getmu();
for(int i = 1; i <= t; i++){
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
if(k == 0) printf("Case %d: %lld\n", i, 0);
else printf("Case %d: %lld\n", i, getans(b / k, d / k));
}
return 0;
}
8、splay
struct SPLAY{
int val[N], sz[N], fa[N], ch[N][2], cnt[N], root, tot;
void update(int x){
sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void debug(){
for(int i = 1; i <= 10; i++)
printf("%d %d %d %d %d\n", i, ch[i][0], ch[i][1], sz[i], cnt[i]);
}
void Rotate(int x){
int y = fa[x], z = fa[y];
int k = (ch[y][1] == x);
ch[z][ch[z][1] == y] = x;
fa[x] = z;
ch[y][k] = ch[x][k ^ 1];
fa[ch[y][k]] = y;
ch[x][k ^ 1] = y;
fa[y] = x;
update(y); update(x);
}
void splay(int x, int pos){
while(fa[x] != pos){
int y = fa[x], z = fa[y];
if(z != pos)
((ch[z][0] == y) ^ (ch[y][0] == x)) ? Rotate(x) : Rotate(y);
Rotate(x);
}
if(pos == 0) root = x;
update(x);
}
void Insert(int x){
int u = root, ff = 0;
while(u && val[u] != x){
ff = u;
u = ch[u][x > val[u]];
}
if(u) {cnt[u]++; splay(u, 0); return;}
u = ++tot;
if(ff) ch[ff][x > val[ff]] = u;
ch[u][0] = ch[u][1] = 0;
fa[u] = ff;
val[u] = x;
cnt[u] = 1;
sz[u] = 1;
splay(u, 0);
}
void Find(int x){
int u = root;
if(!u) return;
while(ch[u][x > val[u]] && x != val[u])
u = ch[u][x > val[u]];
splay(u, 0);
//printf("%d\n", u);
}
int Next(int x, int f){
Find(x);
//debug();
int u = root;
if(val[u] > x && f) return u;
if(val[u] < x && !f) return u;
u = ch[u][f];// printf("%d\n", u);
while(ch[u][f ^ 1]) u = ch[u][f ^ 1];
return u;
}
void Delete(int x){
int last = Next(x, 0);
int next = Next(x, 1);
splay(last, 0);splay(next, last); //debug();
sz[next]--;sz[last]--;
int del = ch[next][0];
if(cnt[del] > 1){
sz[del]--;
cnt[del]--;
splay(del, 0);
}
else ch[next][0] = 0;
//debug();
}
int Rank(int x){
Find(x);
return sz[ch[root][0]];
}
int kth(int k){
k++;
int u = root, now = 0;
while(1){
if(ch[u][0] && k <= sz[ch[u][0]]) u=ch[u][0];
else{
int tmp = sz[ch[u][0]] + cnt[u];
if(k <= tmp) return val[u];
k -= tmp;
u = ch[u][1];
}
}
}
};
SPLAY Splay;
9、prim
留坑
10、dijkstra
void dijkstra(int s, int o, int k){
for(int i = 1; i <= n; i++) dis[i][k] = 1e18;
memset(vis, 0, sizeof(vis));
dis[s][k] = 0;
q.push(mp(0, s));
while(!q.empty()){
ll d = q.top().fi;
int x = q.top().se;
q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(int t = idx[x]; t; t = edge[t].nxt){
E e = edge[t];
if(d + e.w < dis[e.to][k]){
dis[e.to][k] = d + e.w;
q.push(mp(dis[e.to][k], e.to));
}
}
}
}
11、spfa
void SPFA(){
q.push(s);vis[s]=1;
memset(dis,127,sizeof(dis));
dis[s]=0;
while(!q.empty()){
int x=q.front();q.pop();
for(int t=idx[x];t;t=edge[t].nxt){
E e=edge[t];
if(dis[e.to]>dis[x]+e.w){
dis[e.to]=dis[x]+e.w;
if(!vis[e.to]){
vis[e.to]=1;
q.push(e.to);
}
}
}
vis[x]=0;
}
}
12、线段树
#include
#define ll long long
#define N 100005 * 4
#define mid ((l + r) >> 1)
#define L k << 1, l, mid
#define R k << 1 | 1, mid + 1, r
#define O k, l, r
using namespace std;
ll sum[N],tag[N],a[N];
int n,m;
ll read(){
char ch;ll x = 0; bool f = 0;
for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = 1;
for(;'0' <= ch && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
if(f) return -x; return x;
}
void paint(int k, int l, int r, ll z){
sum[k] += z * (r - l + 1);
tag[k] += z;
}
void pushup(int k){
sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
void pushdown(int k, int l, int r){
paint(L, tag[k]);
paint(R, tag[k]);
tag[k] = 0;
}
void build(int k, int l, int r){
if(l == r){
sum[k] = a[l];
tag[k] = 0;
return;
}
build(L);build(R);
pushup(k);return;
}
void add(int k, int l, int r, int x, int y, ll z){
if(x <= l && r <= y){
paint(O, z);
return;
}
pushdown(O);
if(x <= mid) add(L, x, y, z);
if(mid + 1 <= y) add(R, x, y ,z);
pushup(k); return;
}
ll query(int k, int l, int r, int x, int y){
if(x <= l && r <= y) return sum[k];
ll ans = 0;
pushdown(O);
if(x <= mid) ans += query(L, x, y);
if(mid + 1 <= y) ans += query(R, x, y);
pushup(k);
return ans;
}
int main(){
while(scanf("%d%d", &n, &m) == 2){
for(int i = 1; i <= n * 4; i++)
sum[i] = tag[i] = 0;
for(int i = 1; i <= n; i++)
a[i] = read();
build(1, 1, n);
for(int i = 1, x, y, z; i <= m; i++){
char c = getchar();
if(c == 'C'){
x = read();
y = read();
z = read();
add(1, 1, n, x, y, z);
}
if(c == 'Q'){
x = read();
y = read();
printf("%lld\n", query(1, 1, n, x, y));
}
}
}
return 0;
}
13、kmp
void getnext(){
memset(f, 0, sizeof(f));
f[1] = 0; int j = 0; num[1] = 1;
for(int i = 2;i <= la; i++){
while(j && s1[i] != s1[j + 1]) j = f[j];
if(s1[i] == s1[j + 1]) j++;
f[i] = j;
num[i] = num[f[i]] + 1;
}
//for(int i = 1; i <= la; i++) printf("%d : %lld ", i, num[i]);puts("");
}
void kmp(){
int j = 0;
for(int i = 2;i <= la; i++){
while(j && s1[i] != s1[j + 1]) j = f[j];
if(s1[i] == s1[j + 1]) j++;
while(j * 2 > i) j = f[j];
//printf("%d\n", j);
ans = ans * (num[j] + 1) % Mo;
}//puts("");
}
14、manacher
void manacher(){
ans = 0;
for(int i = 1; i <= l + l + 1; i++)
if(i & 1) s[i] = '%';
else s[i] = s1[i / 2];
f[1] = 1; R = 1; pos = 1; l = l + l + 1;
for(int i = 1; i <= l; i++){
if(i <= R) f[i] = min(f[pos * 2 - i], R - i);
else f[i] = 1;
while(i - f[i] >= 1 && i + f[i] <= l && s[i - f[i]] == s[i + f[i]]) f[i]++;
if(i + f[i] > R) {pos = i; R = i + f[i];}
}
}
15、set
#include
#include
#include
using namespace std;
const int N = 200005;
const int inf = 0x7fffffff;
struct Node{
int id, val;
};
bool operator < (const Node a, const Node b){
return a.val < b.val;
}
set s;
int q, x, y;
char opt;
int main(){
while(scanf("%d", &opt) && opt){
if(opt == 1){
scanf("%d%d", &x, &y);
s.insert((Node){x, y});
}
if(opt == 2){
if(s.empty()) {printf("0\n"); continue;}
printf("%d\n", (*(--s.end())).id);
s.erase(--s.end());
}
if(opt == 3){
if(s.empty()) {printf("0\n"); continue;}
printf("%d\n", (*s.begin()).id);
s.erase(s.begin());
}
}
return 0;
}
16、km算法
#include
#include
#include
using namespace std;
const int N = 20005;
const int M = 100005;
struct E {int to, nxt;}edge[M];
bool vis[N];
int left[N], idx[N], tot, n, m, x, y, ans;
struct A{int x, y;} a[N];
bool operator < (A l, A r){return l.x < r.x;}
void addedge(int from, int to){
from++; to++;
//printf("%d %d\n", from, to);
edge[++tot].to = to;edge[tot].nxt = idx[from]; idx[from] = tot;
}
bool dfs(int x){
for(int t = idx[x]; t; t = edge[t].nxt){
E e = edge[t];
if(vis[e.to]) continue;
vis[e.to] = 1;
if(!left[e.to] || dfs(left[e.to])){
left[e.to] = x;
return 1;
}
}
return 0;
}
int main() {
scanf("%d", &n); m = n;
for(int i = 0; i < n; i++){
scanf("%d", &x);
if(x > n / 2) {printf("No Answer\n");return 0;}
x = n - x;
if(i + x < n) addedge(i, i + x + n);
x = n - x;
if(i + x < n) addedge(i, i + x + n);
if(i - x >= 0) addedge(i, i - x + n);
x = n - x;
if(i - x >= 0) addedge(i, i - x + n);
}
for(int i = n; i >= 1; i--){
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
//printf("%d\n", ans);
//for(int i = 1; i <= m; i++) printf("%d %d\n", left[i + n], i);
if(ans != n) {printf("No Answer\n");return 0;}
for(int i = 1; i <= m; i++)
a[i].x = left[i + n], a[i].y = i;
sort(a + 1, a + 1 + m);
for(int i = 1; i < m; i++)
printf("%d ", a[i].y - 1);
printf("%d\n", a[m].y - 1);
return 0;
}
17、dinic
void init(){
memset(idx, 0, sizeof(idx));
memset(a, 0, sizeof(a));
memset(cur, 0, sizeof(0));
tot = 2;
S = 1; T = n;
for(int i=1, x, y, w; i <= m; i++)
scanf("%d%d%d", &x, &y, &w),
addedge(x, y, w, 0), addedge(y, x, 0, 0);
}
bool BFS(){
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
Q.push(S); vis[S] = 1;
while(!Q.empty()){
int x = Q.front(); Q.pop();
for(int t = idx[x]; t; t = edge[t].nxt){
E& e = edge[t];
if(!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
Q.push(e.to);
dis[e.to] = dis[x] + 1;
}
}
}
return vis[T];
}
int DFS(int x, int a){
int flow=0, f;
if(x == T || a == 0) return a;
for(int& i = cur[x]; i; i = edge[i].nxt){
E& e = edge[i];
if(dis[x] + 1 == dis[e.to]){
f=DFS(e.to, min(a,e.cap - e.flow));
if(f > 0){
edge[i].flow += f;
edge[i ^ 1].flow -= f;
flow += f;
a -= f;
if(!a) break;
}
}
}
return flow;
}
int dinic(){
int flow=0;
while(BFS()){
for(int i = 0;i <= n; i++) cur[i] = idx[i];
flow += DFS(S, INF);
}
return flow;
}
18、费用流
bool SPFA(){
Q.push(S);
memset(vis, 0, sizeof(vis));
memset(dis, 127, sizeof(dis));
memset(last, 255, sizeof(last));
memset(cnt, 0, sizeof(cnt));
vis[S] = 1; dis[S] = 0;
while(!Q.empty()){
int x = Q.front();
Q.pop(); vis[x]=0;
for(int t = idx[x]; t; t = edge[t].nxt){
E& e = edge[t];
if(e.cap <= e.flow) continue;
if(dis[e.to] > dis[x] + e.cost){
last[e.to] = x;
edges[e.to] = t;
dis[e.to] = dis[x] + e.cost;
if(!vis[e.to]) {
vis[e.to] = 1;
Q.push(e.to);
}
}
}
}
return (dis[T] != dis[0]);
}
void mcmf(){
int flow = 0; int cost = 0;
while(SPFA()){
//printf("%d\n", flow);
int u = T, f = INF;
while(last[u] != -1){
f = min(edge[edges[u]].cap - edge[edges[u]].flow, f);
u = last[u];
}
u = T;
while(last[u] != -1){
edge[edges[u]].flow += f;
edge[edges[u] ^ 1].flow -= f;
u = last[u];
}
// printf("***%d",f);
flow += f;
cost += dis[T] * f;
}
printf("%d\n", cost);
}
19、tarjan
void tarjan(int x){
dfn[x] = low[x] = ++Time;
S.push(x); ins[x] = 1;
for(int t = idx[x] ; t; t = edge[t].nxt){
E e = edge[t];
if(!dfn[e.to]){
tarjan(e.to);
low[x] = min(low[x], low[e.to]);
}
else if(ins[e.to])
low[x] = min(low[x], dfn[e.to]);
}
int now;
if(dfn[x] == low[x]){
cnt++;
do{
now = S.top();
S.pop();
ins[now] = 0;
col[now] = cnt;
}while(now != x);
}
}
20、割点割边双联通
void dfs(int x,int fa){
int child = 0;
dfn[x] = low[x] = ++Time;
for(int t = idx[x]; t; t = edge[t].nxt){
E e = edge[t];
E ee = (E) {x, e.to};
if(!dfn[e.to]){
S.push(ee);
child++;
dfs(e.to, x);
low[x] = min(low[e.to], low[x]);
if(low[e.to] >= dfn[x]){
iscut[x] = 1;
bcc_cnt++; bcc[bcc_cnt].clear();
for(;;){
E now = S.top(); S.pop();
if(bccno[now.u] != bcc_cnt) {
bcc[bcc_cnt].push_back(now.u);
bccno[now.u] = bcc_cnt;
}
if(bccno[now.v] != bcc_cnt) {
bcc[bcc_cnt].push_back(now.v);
bccno[now.v] = bcc_cnt;
}
if(now.u == x && now.v == e.to) break;
}
}
//if(low[e.to] > dfn[x]) 割边
}
else if(dfn[e.to] < dfn[x] && e.to != fa) {
S.push(ee);
low[x] = min(low[x], dfn[e.to]);
}
}
if(fa == -1 && child == 1) iscut[x] = 0;
}
21、欧拉回路方案
void dfs(int x) {
a[x] = 1;
//printf("%d\n", x);
for(int &t = idx[x]; t; t = edge[t].nxt) {
E e = edge[t];
if(!vis[t / 2]) {
vis[t / 2] = 1;
dfs(e.to);
ans.push_back(e.id);
}
}
}
22、
struct AC{
queue q;
int ch[N][27];
int f[N], last[N], cnt[N];
int ans;
int idx(char c){return c - 'a' + 1;}
int size, now;
void init() {
memset(f, 0, sizeof(f));
memset(last, 0, sizeof(last));
memset(cnt, 0, sizeof(cnt));
ans = 0; size = 0;
memset(ch, 0, sizeof(ch));
}
void insert(char* ss){
now = 0;
for(int i=0; ss[i]; i++){
if(!ch[now][idx(ss[i])])
ch[now][idx(ss[i])] = ++size;
now = ch[now][idx(ss[i])];
}
cnt[now]++;
}
void getfail(){
for(int i = 1; i <= 26; i++)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int r = q.front(); q.pop();
for(int i = 1;i <= 26; i++){
int u = ch[r][i];
if(!u) {ch[r][i] = ch[f[r]][i]; continue;}
q.push(u);
int v = f[r];
while(v && !ch[v][i]) v = f[v];
f[u] = ch[v][i];
last[u] = cnt[f[u]] ? f[u] : last[f[u]];
}
}
}
void calc(int x){
if(x == 0) return;
ans += cnt[x];
cnt[x] = 0;
calc(last[x]);
}
void find(char *s){
int j=0;
for(int i = 0; s[i]; i++){
int c = idx(s[i]);
j = ch[j][c];
if(cnt[j]) calc(j);
else calc(last[j]);
}
}
};
23、计算几何
int sgn (double x) {
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
double dist (double x, double y) {
return sqrt(x *x + y * y);
}
struct Point {
double x, y;
Point(){}
Point(double _x, double _y) {
x = _x; y = _y;
}
void input() {
scanf("%lf%lf", &x, &y);
}
void output() {
printf("%lf %lf\n", x, y);
}
bool operator == (const Point &b) {
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (const Point &b) {
return sgn(y - b.y) == 0 ? sgn(x - b.x) < 0 : sgn(y - b.y) < 0;
}
Point operator + (const Point &b) {
return Point(x + b.x, y + b.y);
}
Point operator - (const Point &b) {
return Point(x - b.x, y - b.y);
}
double operator ^ (const Point &b) {
return x * b.y - y * b.x;
}
double operator * (const Point &b) {
return x * b.x + y * b.y;
}
double dis (const Point &b) {
return dist(x - b.x, y - b.y);
}
}p;
struct Line {
Point s, e;
Line(){}
Line(Point _s, Point _e) {
s = _s; e = _e;
}
void input() {
s.input(); e.input();
}
void output() {
puts("line:");
s.output(); e.output();
}
// 1 left 2 right 3 on
int relation (Point p) {
int c = sgn((p - s) ^ (e - s));
//printf("c : %d\n", c);
if(c < 0) return 1;
if(c > 0) return 2;
return 3;
}
void adjust() {
if(e < s) swap(e, s);
}
bool operator < (const Line &b) {
return s < b.s || (s == b.s && e < b.e);
}
}line[N], l;
24、2-sat
bool dfs(int x) {
if(mark[x ^ 1]) return 0;
if(mark[x]) return 1;
mark[x] = 1;
s[++c] = x;
for(int t = idx[x]; t; t = edge[t].nxt)
if(!dfs(edge[t].to)) return 0;
return 1;
}
bool solve() {
if (!dfs(1)) return false;
for(int i = 2; i <= 2 * n - 1; i += 2) {
if(!mark[i] && !mark[i + 1]) {
c = 0;
if(!dfs(i)) {
for(int j = 1; j <= c; j++)
mark[s[j]] = 0;
c = 0;
if(!dfs(i + 1)) return 0;
}
}
}
return 1;
}
25、后缀数组
//后缀数组倍增算法,假设输入的字符串为s[1..n]
//sa[i]表示字典序第i小的后缀在串s中的位置
//Rank[i]表示从位置i开始的后缀在串s的所有后缀中排第几
//height[i]表示字典序第i-1小的后缀与字典序第i小的后缀的最长公共前缀
void buildsa(int m){
int i,*x=t1,*y=t2;
for(i = 1; i <= m; i++) c[i] = 0;
for(i = 1; i <= n; i++) c[x[i] = s[i]]++;
for(i = 1; i <= m; i++) c[i] += c[i - 1];
for(i = n; i >= 1; i--) sa[c[x[i]]--] = i;
for(int k = 1; k <= n;k <<= 1){
int p = 0;
for(i = n - k + 1; i <= n; i++) y[++p] = i;
for(i = 1; i <= n; i++) if(sa[i] > k) y[++p] = sa[i] - k;
for(i = 1; i <= m; i++) c[i] = 0;
for(i = 1; i <= n; i++) c[x[y[i]]]++;
for(i = 1; i <= m; i++) c[i] += c[i - 1];
for(i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
swap(x, y); p = 1; x[sa[1]] = 1;
for(i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]]
&& y[sa[i] + k] == y[sa[i - 1] + k]) ?
p : ++p;
if(p >= n) break;
m = p;
}
}
void getheight(){
int i, j, k = 0;
for(i = 1; i <= n; i++) Rank[sa[i]] = i;
for(i = 1; i <= n; i++){
if(k) k--;
j=sa[Rank[i] - 1]; // sa[rank[i]]=i;
while(s[j+k] == s[i+k]) k++;
height[Rank[i]] = k;
}
}
26、树链剖分
#include
#include
#include
#include
using namespace std;
const int M=200010;
const int inf=0x7fffffff;
struct E {int to,nxt;}edge[M*2];
struct SEG {int l,r,sum,mx;}tree[M*2];
int v[M],fa[M],size[M],son[M],dep[M],top[M],w[M],f[M];
int n,q,tot=1,idx[M],vis[M],cnt,retsum,retmax;
void addedge(int from,int to){
edge[tot].to=to;edge[tot].nxt=idx[from];idx[from]=tot++;
}
void init(){
scanf("%d",&n);
for(int i=1;i>1;
build_seg(k<<1,a,mid);build_seg(k<<1|1,mid+1,b);
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
void change(int k,int a,int x){
if(atree[k].r) return;
if(a==tree[k].l && a==tree[k].r)
{tree[k].mx=x,tree[k].sum=x;return;}
change(k<<1,a,x);change(k<<1|1,a,x);
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
int getsum(int k,int a,int b){
if(btree[k].r) return 0;
if(a<=tree[k].l && tree[k].r<=b) return tree[k].sum;
return getsum(k<<1,a,b)+getsum(k<<1|1,a,b);
}
int getmax(int k,int a,int b){
if(btree[k].r) return -inf;
if(a<=tree[k].l && tree[k].r<=b) return tree[k].mx;
return max(getmax(k<<1,a,b),getmax(k<<1|1,a,b));
}
void solve(int x,int y,int opt){
int f1=top[x],f2=top[y];
retmax=-inf,retsum=0;
while(f1!=f2){
if(dep[f1]
27、莫队算法
所以有一个比较优雅的替代品。那就是先对序列分块。然后对于所有询问按照L所在块的大小
排序。如果一样再按照R排序。然后按照排序后的顺序计算。为什么这样计算就可以降低复杂度呢。
一、i与i+1在同一块内,r单调递增,所以r是O(n)的。由于有n^0.5块,所以这一部
分时间复杂度是n^1.5。
二、i与i+1跨越一块,r最多变化n,由于有n^0.5块,所以这一部分时间复杂度是n^1.5
三、i与i+1在同一块内时变化不超过n^0.5,跨越一块也不会超过2*n^0.5,不
妨看作是n^0.5。由于有n个数,所以时间复杂度是n^1.5
于是就变成了O(n^1.5)了。
而我们知道 莫队算法的O(n^1.5)是基于O(1)得到[l-1,r]结果的
然而这道题 查逆序对 需要O(logn)时间用树状数组完成= =
所以复杂度O(n^1.5*logn)。。
#include
#include
#include
#include
#define lowbit(pos) pos&(-pos)
using namespace std;
const int M=50010;
int a[M],disc[M],bl[M],c[M];
int N,Q;
struct qu {int l,r,id,ans;}q[M];
bool cmp(qu x,qu y){
if(bl[x.l]==bl[y.l]) return x.rr) {r++;add(a[r],1);now+=r-l+1-query(a[r]);}
while(q[i].l>l) {add(a[l],-1);now-=query(a[l]-1);l++;}
while(q[i].r
28、点分治
#include
#include
#include
using namespace std;
const int inf = 0x7fffffff;
const int N = 10005;
int n, tot, idx[N], root, ans, sum, sz[N], f[N], d[N], dep[N], p, K;
bool can[N];
struct E {int to, nxt, w;}edge[N * 2];
void init() {
memset(idx, 0, sizeof(idx));
tot = 1;
memset(can, 0, sizeof(can));
sum = n; ans = 0; root = 0; f[root] = inf;
for(int i = 0; i < N; i++) can[i] = 1;
}
void addedge(int from, int to, int w) {
edge[++tot].to = to; edge[tot].nxt = idx[from]; idx[from] = tot; edge[tot].w = w;
}
void getroot(int x, int fa) {
sz[x] = 1; f[x] = 0;
for(int t = idx[x]; t; t = edge[t].nxt) {
E e = edge[t];
if(e.to == fa || !can[e.to]) continue;
getroot(e.to, x);
sz[x] += sz[e.to];
f[x] = max(sz[e.to], f[x]);
}
sz[x]++;
f[x] = max(sum - sz[x], f[x]);
if(f[x] < f[root]) root = x;
}
void getdeep(int x, int fa) {
d[++p] = dep[x];
for(int t = idx[x]; t; t = edge[t].nxt) {
E e = edge[t];
if(e.to == fa || can[e.to] == 0) continue;
dep[e.to] = dep[x] + e.w;
getdeep(e.to, x);
}
}
int calc(int x, int now) {
int ret = 0;
dep[x] = now; p = 0;
getdeep(x, -1); //printf("%d : ", x);
//for(int i = 1; i <= p; i++) printf("%d ", d[i]); puts("");
sort(d + 1, d + 1 + p);
int l = 1, r = p;
for(int l = 1; l <= p; l++) {
while(d[l] + d[r] > K && l < r) r--;
if(l >= r) break;
ret += (r - l);
}
return ret;
}
void work(int x) {
ans += calc(x, 0);
//printf("%d %d\n", can[3], can[4]);
can[x] = 0;
for(int t = idx[x]; t; t = edge[t].nxt) {
E e = edge[t];
if(!can[e.to]) continue;
//printf("%d\n", e.to);
ans -= calc(e.to, e.w);
sum = sz[e.to];
root = 0;
getroot(e.to, -1); //printf("%d %d\n", e.to, root); return;
work(root);
}
}
int main() {
while(scanf("%d%d", &n, &K) && n + K) {
init();
for(int i = 1, x, y, z; i < n; i++)
scanf("%d%d%d", &x, &y, &z),
addedge(x, y, z), addedge(y, x, z);
getroot(1, -1);
work(root);
printf("%d\n", ans);
}
return 0;
}
29、二维rmq
int getmax(int X1, int Y1, int X2, int Y2) {
int k1 = LOG[X2 - X1 + 1];
int k2 = LOG[Y2 - Y1 + 1];
X2 = X2 - (1 << k1) + 1;
Y2 = Y2 - (1 << k2) + 1;
return max(max(maxx[X1][Y1][k1][k2], maxx[X1][Y2][k1][k2]),
max(maxx[X2][Y1][k1][k2] ,maxx[X2][Y2][k1][k2]));
}
int getmin(int X1, int Y1, int X2, int Y2) {
int k1 = LOG[X2 - X1 + 1];
int k2 = LOG[Y2 - Y1 + 1];
X2 = X2 - (1 << k1) + 1;
Y2 = Y2 - (1 << k2) + 1;
return min(min(minn[X1][Y1][k1][k2], minn[X1][Y2][k1][k2]),
min(minn[X2][Y1][k1][k2] ,minn[X2][Y2][k1][k2]));
}
int main() {
scanf("%d%d%d", &n, &b, &k);
LOG[0] = -1;
for(int i = 1; i <= 254; i++)
LOG[i] = ((i & (i - 1)) == 0) ?
LOG[i - 1] + 1 : LOG[i - 1];
for(int i = 1, x; i <= n; i++)
for(int j = 1; j <= n; j++)
scanf("%d", &x),
minn[i][j][0][0] = maxx[i][j][0][0] = x;
for(int ii = 0; ii <= LOG[n]; ii++)
for(int jj = 0; jj <= LOG[n]; jj++)
if(ii + jj)
for(int i = 1; i + (1 << ii) - 1 <= n; i++)
for(int j = 1; j + (1 << jj) - 1 <= n; j++)
if(ii)
minn[i][j][ii][jj] = min(minn[i][j][ii - 1][jj],
minn[i + (1 << (ii - 1))][j][ii - 1][jj]),
maxx[i][j][ii][jj] = max(maxx[i][j][ii - 1][jj],
maxx[i + (1 << (ii - 1))][j][ii - 1][jj]);
else
minn[i][j][ii][jj] = min(minn[i][j][ii][jj - 1],
minn[i][j + (1 << (jj - 1))][ii][jj - 1]),
maxx[i][j][ii][jj] = max(maxx[i][j][ii][jj - 1],
maxx[i][j + (1 << (jj - 1))][ii][jj - 1]);
for(int i = 1, x, y; i <= k; i++) {
scanf("%d%d", &x, &y);
printf("%d\n", getmax(x, y, x + b - 1, y + b - 1) -
getmin(x, y, x + b - 1, y + b - 1));
}
return 0;
}
30、rmq
int getmax(int l, int r) {
int k = LOG[r - l + 1];
r = r - (1 << k) + 1;
return max(maxx[l][k], maxx[r][k]);
}
int getmin(int l, int r) {
int k = LOG[r - l + 1];
r = r - (1 << k) + 1;
return min(minn[l][k], minn[r][k]);
}
int main(){
LOG[0] = -1;
for(int i = 1; i < N; i++)
LOG[i] = ((i & (i - 1)) == 0) ?
LOG[i - 1] + 1 : LOG[i - 1];
while(scanf("%d%d", &n, &q) != EOF){
for(int i = 1; i <= n; i++)
scanf("%d", &minn[i][0]),
maxx[i][0] = minn[i][0];
for(int j = 1; j <= 19; j++)
for(int i = 1; i <= n; i++){
int k = i + (1 << j) - 1;
if(k > n) break;
minn[i][j] = min(minn[i][j - 1],
minn[i + (1 << (j - 1))][j - 1]);
maxx[i][j] = max(maxx[i][j - 1],
maxx[i + (1 << (j - 1))][j - 1]);
}
for(int i = 1, l, r; i <= q; i++) {
scanf("%d%d", &l, &r);
printf("%d\n", getmax(l, r) -
getmin(l, r));
}
}
return 0;
}
31、树上rmq
void dfs(int x, int f) {
vis[x] = 1;
for(int t = idx[x]; t; t = edge[t].nxt) {
E e = edge[t];
if(e.to == f) continue;
if(vis[e.to]) {
X = x; Y = e.to; W = e.w; continue;
}
dep[e.to] = dep[x] + 1;
fa[e.to][0] = x;
w[e.to][0] = e.w;
for(int k = 1; k <= LOG[dep[e.to]]; k++)
fa[e.to][k] = fa[fa[e.to][k - 1]][k - 1],
w[e.to][k] =
w[e.to][k - 1] + w[fa[e.to][k - 1]][k - 1];
dfs(e.to, x);
}
}
ll query(int x, int y) {
ll ans = 0;
int h = dep[y] - dep[x];
while(h > 0) {
ans += w[y][LOG[h]];
y = fa[y][LOG[h]];
h = dep[y] - dep[x];
}
h = dep[x] - dep[y];
while(h > 0) {
ans += w[x][LOG[h]];
x = fa[x][LOG[h]];
h = dep[x] - dep[y];
}
if(x == y) return ans;
h = dep[y];
for(int k = LOG[h]; k >= 0; k--)
if(fa[x][k] != fa[y][k]) {
ans += w[x][k];
ans += w[y][k];
x = fa[x][k];
y = fa[y][k];
}
ans += (w[x][0] + w[y][0]);
return ans;
}
32、fft
#include
#include
#include
#include
#include
#define N 300000
#define pi acos(-1.0)
using namespace std;
typedef complex cd;
char s1[N],s2[N];
cd f[N],g[N],eps[N],c_eps[N];
int n,m,a[N];
void init(){
for(int i=0;ij) swap(x[i],x[j]);
for(int l=n>>1;(j^=l)>=1);
}
for(int i=2;i<=n;i<<=1){
int m=i>>1;
for(int j=0;j=0;i--) printf("%d",a[i]);
return 0;
}
33、错排
34、莫队算法:至少存在k次的数
#include
#include
#include
#include
#define N 100005
struct Q{
int l,r,k,ans,id;
}q[N];
int n,m,a[N],num[N],cnt[N],block[N],tot[N],End[N],Begin[N];
using namespace std;
int read(){
char ch=getchar();int f=1,x=0;
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
bool cmp(Q x,Q y){
return block[x.l]q[i].r;r--) upd(r,-1);
for(;l>q[i].l;l--) upd(l-1,1);
for(;l
35、最小表示法
#include
#include
#include
using namespace std;
int T;
char s[20005];
int MinR(){
int l=strlen(s+1);
for(int i=l+1;i<=l+l;i++) s[i]=s[i-l];
int i=1,j=2,k;
while(i<=l&&j<=l){
k=0;
while(s[i+k]==s[j+k]&&ks[j+k])
if(i+k+1>j) i=i+k+1;
else i=j+1;
else
if(j+k+1>i) j=j+k+1;
else j=i+1;
}
if(i<=l) return i;
else return j;
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&T);
while(T--){
scanf("%s",s+1);
printf("%d\n",MinR());
}
return 0;
}
36、lucas定理
#include
#include
#include
#define Mo 10007
#define ll long long
using namespace std;
const int N=10010;
ll fac[N];
ll n,m;
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1;y=0;return;}
else{exgcd(b,a%b,y,x);y-=(a/b)*x;}
}
ll inv(ll a){
ll x,y;
exgcd(a,10007,x,y);
return (x%Mo+Mo)%Mo;
}
ll C(ll n,ll m){
if(m==0) return 1;
if(n