新型快读

Creeper_LKF

2018-02-07 09:35:34

Personal

这次又是基于get_char()的优化,但是用到了更高级的东西: ``` #include <cstdio> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> using namespace std; int main(){ char *data; int size = lseek(0, 0, SEEK_END); data = (char *) mmap( NULL, size ,PROT_READ, MAP_PRIVATE, 0, 0 ); fwrite(data, 1, size, stdout); return 0; } ``` mmap:直接把文件映射到内存,比fread快,因为: 1.read(fread)是一种阻塞系统调用的行为 2.会以内核为缓冲而导致占用CPU时间的内存拷贝 3.没有显示地通知从文件的某个位置开始,导致需要每次使用lseek 上面代码的stdin的标识为0,所以mmap先从stdin映射输入到data内,然后此题为直接输出。 那些标号在OI中无需关注,背背就好了。 注意这种快读有几个使用要求: 1.不接受键盘输入 2.只能在linux等unix或类unix下跑 例如在P3205下跑快读,代码如下,其中还加入了一些莫名奇妙但是没用的优化: ``` // luogu-judger-enable-o2 #include <cstdio> #include <sys/mman.h> #include <unistd.h> using namespace std; #define MAXN 1005 #define MODS 19650827 int num[MAXN] __attribute__ ((aligned(64))); int dp[MAXN][MAXN][2] __attribute__ ((aligned(64))); int main(){ int n = 0; register int i, j; register char *pc = (char *) mmap(NULL, lseek(0, 0, SEEK_END), PROT_READ, MAP_PRIVATE, 0, 0), c; while ((c = *pc++) < 48); while (n = n * 10 + c - 48, (c = *pc++) >= 48); for(i = 1; i <= n; i++){ int &p = num[i]; while ((c = *pc++) < 48); while (p = p * 10 + c - 48, (c = *pc++) >= 48); } for(i = 1; i <= n; i++) dp[i][i][0] = 1; for(i = n; i >= 1; i--){ int (*px) [2] = dp[i]; for(j = i; j <= n; j++){ int &p0 = px[j][0], &p1 = px[j][1]; if(num[i] < num[j]) p1 += px[j - 1][0], p0 += dp[i + 1][j][1]; if(num[i] < num[i + 1]) p0 += dp[i + 1][j][0]; if(num[j] > num[j - 1]) p1 += px[j - 1][1]; if(p0 >= MODS) p0 -= MODS; if(p1 >= MODS) p1 -= MODS; } } printf("%d", (dp[1][n][0] + dp[1][n][1]) % MODS); return 0; } ``` 又一次更新:Luogu4047 这是我和某大佬轮流卡常的结果: ![](https://cdn.luogu.com.cn/upload/pic/14270.png) 然而多亏这个快读。所以最后这个快读的函数封装版就在下面,其中get_char部分用指针控制,此部分只有1行!不需要开额外数组,可能(可能)在某些评测系统下会忽略快读的buf空间。 ``` #include <cmath> #include <cstdio> #include <fcntl.h> #include <unistd.h> #include <algorithm> #include <sys/mman.h> using namespace std; #define Finline __inline__ __attribute__ ((always_inline)) char *pc = (char *) mmap(NULL, lseek(0, 0, SEEK_END), PROT_READ, MAP_PRIVATE, 0, 0); inline int read(){ int num = 0; char c; while ((c = *pc++) < 48); while (num = num * 10 + c - 48, (c = *pc++) >= 48); return num; } inline void Swap(int &a, int &b){ int t = a; a = b; b = t; } Finline void upmin(double &a, const double &b){ if(a > b) a = b; } Finline void upmax(int &a, const int &b){ if(a > b) a = b; } int tot, n, k, cnt; int x[1001], y[1001]; double ans = 0x3f3f3f3f3f3f; int father[1001], rnk[1001]; inline void Init(){ for(int i = 1; i <= n; i++) father[i] = i; } inline int Get_Father(int u){ return father[u] == u ? u : father[u] = Get_Father(father[u]); } inline void Merge(int fu, int fv){ fu = Get_Father(fu), fv = Get_Father(fv); if(rnk[fu] > rnk[fv]) Swap(fu, fv); father[fu] = fv; upmax(rnk[fv], rnk[fu] + 1); } struct P{ int u, v; double dis; Finline bool operator < (const P &tar) const { return dis < tar.dis; } }edge[500501]; inline int pow2(int tar){ return tar * tar; } signed main(){ freopen("in.in", "r", stdin); n = read(), k = read(), k = n - k; Init(); for(int i = 1; i <= n; i++){ x[i] = read(), y[i] = read(); for(int j = 1; j < i; j++) edge[++tot] = (P){i, j, sqrt(pow2(x[i] - x[j]) + pow2(y[i] - y[j]))}; } sort(edge + 1, edge + 1 + tot); for(int i = 1; i <= tot; i++){ int u = edge[i].u, v = edge[i].v; if(Get_Father(u) != Get_Father(v)){ if(cnt == k){ printf("%.2lf", edge[i].dis); return 0; } cnt ++; Merge(u, v); } } return 0; } ``` 最后这篇文章大致更新完毕。 License: ![](https://licensebuttons.net/l/by-nc-sa/3.0/cn/88x31.png) 本作品采用[知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/)进行许可。