vis

洛谷 P4886 快递员

怎甘沉沦 提交于 2019-11-30 21:45:26
传送门 介是你没有体验过的 \(chuan\) 新做法。 暴力点分治算出每个点作为中心时的答案。 对于路径 \(c\rightarrow u\rightarrow c\rightarrow v\rightarrow c\) 的长度除以 \(2\) ,我们可以看做 \(dis(u,v)+c\) 到路径 \((u,v)\) 的距离乘 \(2\) 。 把路径分成两类: 经过分治中心的: 对于这种路径, \(dfs\) 一遍树,当脱离了某条路径时,比如走边 \((2,4)\) 或 \((2,5)\) ,开始计算该路径的贡献。假设走边 \((x,y)\) 脱离了该路径,则 \(y\) 子树内每个点 \(i\) 都会有 \(dis(i,x)\times 2+dis(u,v)\) 的贡献。 具体实现:给每条边维护一个权值 \(V\) ,对每条路径上的边的 \(V\) 对 \(dis(u,v)\) 取 \(\max\) 。算出每个点每条出边 \(V\) 的最大值和次大值。 \(dfs\) 时维护当前最大贡献 \(now\) ,对每个点,等于该点最大值的边选次小值更新 \(now\) ,否则选最大值,累加边权乘 \(2\) 即可。 这样会发现从根节点开始 \(dfs\) 时会出现这种情况: 此时,红色路径和绿色路径为最大和次大。 由于一条路径可能会占据根节点的两条出边,维护最大值和次大值就出 \

有趣的新手练习题

别说谁变了你拦得住时间么 提交于 2019-11-30 19:45:01
hdu 1079 记忆化搜索 #include<bits/stdc++.h> #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std;//head int casn,n,m,k,kasn; int vis[2100][15][40]; int day[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31}}; int dfs(int y,int m,int d){ if(~vis[y][m][d]) return vis[y][m][d]; int flag=0,r=(y%4==0&&y%100!=0)||(y%400==0); if(m<12&&day[r][m+1]>=d) flag|=!dfs(y,m+1,d); if(!flag){ if(d==day[r][m]){ if(m==12)flag|=!dfs(y+1,1,1); else flag|=!dfs(y,m+1,1); }else flag|=!dfs(y,m,d+1); } return vis[y

Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解

柔情痞子 提交于 2019-11-30 19:36:12
A..B略 C 对当前的值排序,再二分答案,然后对于(i%x==0 && i%y==0)放入大的,再放其他的贪心解决即可。 #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<map> #define LL long long #define lson rt<<1 #define rson rt<<1|1 using namespace std; const int maxx = 2e5+7; int a[maxx]; int vis[maxx]; LL k; LL aa,bb; int x,y,n; bool check(int mid){ LL ans=0; int top=0; for (int i=1;i<=mid;i++){ if (i%x==0 && i%y==0){ vis[i]=a[++top]; ans=(LL)ans+vis[i]/100*(aa+bb); }else { vis[i]=0; } } for (int i=1;i<=mid;i++){ if (i%y==0 && !vis[i]){ vis[i]=a[++top]; ans=(LL)ans+vis[i]/100*bb; } } for (int i=1;i<=mid;i++){

Luogu P5020 货币系统

我们两清 提交于 2019-11-30 19:15:40
gate 我太菜了,看了标签是背包还不知道是怎么回事qaq 看了下题解,意识到这是个类似素数筛的东西。 感性理解可以发现,原货币系统中能被表示出来的是可以不选的,剩下的就是要选的。所以最小的一定要选,把原货币系统从小到大排序。 枚举原货币系统中的货币a[i],枚举金额j(a[i]+1<j<a[n]) 如果j-a[i]可以表示,那么通过a[i],j就也可以表示了。用这种方式判断。 核心代码 for(int i = 1; i <= n; i++) { if(vis[a[i]]) continue; vis[a[i]] = true; ans++; for(int j = a[i]+1; j <= a[n]; j++) if(vis[j-a[i]]) vis[j] = true; } 唉——代码好短 #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq #include<algorithm> using namespace std; const int maxn = 30005; int t,n,a[maxn],vis[maxn],ans; void init() { ans = 0; memset(a,0,sizeof(a)); memset(vis,0

8.26

流过昼夜 提交于 2019-11-30 18:22:16
又双叒叕把U盘忘在寝室了,所以把今下午的代码拷在这里 /* reference: translation: 有q次操作。每次会选定一个矩形区域。具体的每次给一组(x_1,y_1),(x_2,y_2)表示矩阵的左 下角和右上角。在这个矩阵所覆盖的每一个格子里,累加一个积木块。每个积木块可以可以抽 象为一个的正方体。现在,Venn想知道他们堆出来的物体的表面积。 solution: 【首先这并不是在线的询问,而是只询问一次,所以我们考虑对每个操作O(1)差分一下。】 1.n*m*q的暴力算法显然不可取,采用二维差分O(1)预处理,O(n^2)查询a[i][j]的高度。 2.如果这个位置有高度,ans+=2;(上表面和下表面),其他四个面看周围四个的心情 trigger: note: *二维差分 *表面积问题 record: 这道题开long long 会爆内存………………………………………… date: 2019.08.26 */ #define N 5001 int n,m,q; int cnt[N][N]; int main(){ rd(n);rd(m);rd(q); while(q--){ int x1,y1,x2,y2;rd(x1);rd(y1);rd(x2);rd(y2); cnt[x1][y1]++; cnt[x1][y2+1]--; cnt[x2+1][y1]--;

【acwing板子大全】图论与搜索

早过忘川 提交于 2019-11-30 18:19:48
树与图的遍历 时间复杂度 O(n+m), n表示点数,m表示边数 (1) 深度优先遍历 —— 模板题 AcWing 846. 树的重心 int dfs(int u){ vis[u]=1; int son_size=1,now=0; ee(i,u){ int v=e[i].v; if(!vis[v]){ int t=dfs(v); now=max(now,t); son_size+=t; } } now=max(now,n-son_size); ans=min(ans,now); return son_size; } (2) 宽度优先遍历 —— 模板题 AcWing 847. 图中点的层次 queue<int>q; inline void spfa(){ mem(dis,0x3f); mem(vis,0); q.push(1); vis[1]=1; dis[1]=0; while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; ee(i,u){ int v=e[i].v,w=e[i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } } 拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列 时间复杂度 O(n

差分约束

℡╲_俬逩灬. 提交于 2019-11-30 18:18:39
例题1 interval 最长路 数组下标为-1怎么处理 ”标准输出太巨怎么办“ /* reference: translation: solution: 1---->在a[i]和b[i]+1之间连一条长度为c[i]的有向边 2---->在i和i+1之间连一条长度为0的有向边 3---->在i+1和i之间连一条长度为-1的有向边 trigger: note: *我们在i-1和i之间连长度为0的有向边,在i和i-1之间连长度为-1的有向边 因为i的范围是0-50000所以i-1会变成负数,我们都知道,若数组的下标为负,程序会运行 错误,所以我们不妨给所有的变量加1,这样就不会出现负下标了 date: 2019.09.05 */ const int N=1e6+10; int head[N],edge_num,maxx=INT_MIN,minn=INT_MAX; int n,m,s; int dis[N]; bool vis[N]; struct edge{ int v,w,next; }e[N]; inline void add(int u,int v,int w){e[++edge_num].v=v;e[edge_num].w=w;e[edge_num].next=head[u];head[u]=edge_num;} queue<int>q; inline void spfa(){

[一本通学习笔记] 广度优先搜索和优化

邮差的信 提交于 2019-11-30 15:56:15
BFS的题目没什么好说的,通常优化都是判断可行性,或者状压以后记忆化。几道例题都非常基础。 #10027. 「一本通 1.4 例 2」魔板 暴力写出置换即可。 #include <bits/stdc++.h> using namespace std; int buf[9],tar,ans,src; char vis[99999999]; map <int,string > sta; void A() { swap(buf[1],buf[5]); swap(buf[2],buf[6]); swap(buf[3],buf[7]); swap(buf[4],buf[8]); } void B() { int t1=buf[4], t2=buf[8]; buf[4]=buf[3]; buf[8]=buf[7]; buf[3]=buf[2]; buf[7]=buf[6]; buf[2]=buf[1]; buf[6]=buf[5]; buf[1]=t1; buf[5]=t2; } void C() { int t=buf[2]; buf[2]=buf[6]; buf[6]=buf[7]; buf[7]=buf[3]; buf[3]=t; } int compress() { int ret = 0; for(int i=1;i<=8;i++) ret=ret*10+buf[i]; return

棋盘游戏

你离开我真会死。 提交于 2019-11-30 15:53:25
题目描述 思路 bfs主要问题就是走重复路的问题,需要设置一个vis数组防止走重复路,怎么把一个二维数组表示成一个数,扩展来说就是怎么把状态表示成一个数,看了别人的代码,可以二进制的数来记录状态,4x4的数组状态不会超过2^(17)。 然后就是怎么走的问题,规定只能向下,下右走,而向上,向左就是向下,向右的逆运算。if筛选能够向下,向右走的点就可以了。 代码 #include <cstdio> #include <cstring> #include <queue> char st[5][5], ed[5][5]; int js[5][5], num_ed, tmp, cur, v, vis[135000]; std::queue<int> q; void init() { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { js[i][j] = 1 << (i * 4 + j); } } } int get(char arr[][5]) { int res = 0; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { res += js[i][j] * (arr[i][j] - '0'); } } return res; } void trans