• P1494 [国家集训队]小Z的袜子


    P1494 [国家集训队]小Z的袜子

    题目

    传送门

    思路

    其实挺简单的一个莫队,直接把莫队模板add(),earse()改改即可,另外用到一些组合数学,也不再赘述,详见代码

    另外,还要注意最大数据可能超出int范围(分子(分母)最大值约为2.5*10^10),用unsigned int即可

    代码

    AC代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define uni unsigned int
    #define nn 100010
    using namespace std;
    int read() {
    	int re = 0;
    	char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9')  
    		re = (re << 1) + (re << 3) + c - '0',
    		c = getchar();
    	return re;
    }
    struct node{
    	int l , r , id;
    }ask[nn];
    int t;
    bool cmp(node a , node b) {
    	return (a.l / t != b.l / t) ? (a.l / t < b.l / t) : (a.r < b.r);
    }
    
    uni num[nn];
    int n , q;
    uni a[nn];
    uni cnt;
    uni ans[nn][3];
    
    void add(int l , int r) {
    	if(l == 0)++l;
    	if(r < l)return;
    	for(int i = l ; i <= r ; i++) {
    		if(num[a[i]] != 0)
    			cnt -= num[a[i]] * (num[a[i]] - 1) / 2u;
    		++num[a[i]];
    		cnt += num[a[i]] * (num[a[i]] - 1) / 2u;
    	}
    }
    void earse(int l , int r) {
    	if(l == 0)++l;
    	if(r < l)return;
    	for(int i = l ; i <= r ; i++) {
    		cnt -= num[a[i]] * (num[a[i]] - 1) / 2u;
    		--num[a[i]];
    		if(num[a[i]] != 0)
    			cnt += num[a[i]] * (num[a[i]] - 1) / 2u;
    	}
    }
    uni gcd(uni a , uni b){
    	return b == 0 ? a : gcd(b , a % b);
    }
    int main() {	
    	n = read() , q = read();
    	for(int i = 1 ; i <= n ; i++)
    		a[i] = read();
    	int q_ = q;
    	for(int i = 1 , j = 0 ; i <= q ; i++) {
    		++j;
    		ask[i].l = read() , ask[i].r = read() , ask[i].id = j;
    		while(ask[i].l == ask[i].r && i <= q) {
    			ans[j][0] = 0 , ans[j][1] = 1;
    			--q, ++j;
    			if(i > q)break;
    			ask[i].l = read() , ask[i].r = read() , ask[i].id = j;
    		}
    	}
    	t = sqrt(n);
    	sort(ask + 1 , ask + q + 1 , cmp);
    	
    	for(int i = 1 ; i <= q ; i++) {
    		earse(ask[i - 1].l , ask[i].l - 1);
    		add(ask[i - 1].r + 1 , ask[i].r);
    		
    		earse(ask[i].r + 1 , ask[i - 1].r);
    		add(ask[i].l , ask[i - 1].l - 1);
    		
    		ans[ask[i].id][0] = cnt;
    		ans[ask[i].id][1] = ((long long)ask[i].r - ask[i].l) * (ask[i].r - ask[i].l + 1) / 2;
    		
    	}
    	for(int i = 1 ; i <= q_ ; i++) {
    		int tmp = 1;
    		tmp = gcd(ans[i][0] , ans[i][1]);
    		printf("%lld/%lld
    " , ans[i][0] / tmp , ans[i][1] / tmp);
    	}
    	return 0;
    } 
    

    暴力

    未用unsigned int处理

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #define nn 100010
    using namespace std;
    int read() {
    	int re = 0;
    	char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9')  
    		re = (re << 1) + (re << 3) + c - '0',
    		c = getchar();
    	return re;
    }
    int gcd(int a , int b) {
    	return b == 0 ? a : gcd(b , a % b);
    }
    int vis[nn];
    int a[nn];
    int n , q;
    int main() {
    	n = read(), q = read();
    	for(int i = 1 ; i <= n ; i++)
    		a[i] = read();
    	
    	for(int i = 1 ; i <= q ; i++) {
    		memset(vis , 0 , sizeof(vis));
    		int l = read() , r = read();
    		if(l == r) {
    			puts("0/1");
    			continue;
    		}
    		for(int j = l ; j <= r ; j++)
    			vis[a[j]]++;
    			
    		int cnt = 0;
    		for(int j = 1 ; j <= n ; j++)
    			if(vis[j] != 0)
    				cnt += vis[j] * (vis[j] - 1) / 2;
    		int tmp = (r - l) * (r - l + 1) / 2;
    		printf("%d/%d
    " , cnt / gcd(cnt , tmp) , tmp / gcd(cnt , tmp));
    	}
    	return 0;
    } 
    

    数据生成

    #include <bits/stdc++.h>
    using namespace std;
    int random(int r , int l = 1) {
    	return r == l ? l : (long long) rand() * rand() % (r - l) + l;
    }
    int main() {
    	srand((unsigned)time(0));
    	int n = random(10000);
    	int q = random(10000);
    	printf("%d %d
    " , n , q);
    	for(int i = 1 ; i <= n ; i++)
    		printf("%d " , random(n));
    	putchar('
    ');
    	for(int i = 1 ; i <= q ; i++) {
    		int l = random(n) , r = random(n);
    		if(l > r)swap(l , r);
    		printf("%d %d
    " , l , r);
    	}
    	return 0;
    }
    
  • 相关阅读:
    SQL Server 日期函数:某天是星期几?
    DZNEmptyDataSet,优秀的空白页或者出错页封装
    SVN文件排除
    Android开发艺术探索读书笔记——进程间通信
    HDU 2110 Crisis of HDU
    Android4.4之后休眠状态下Alarm不准时的问题
    Android App性能測试
    Java笔试面试题整理第一波
    美国大学计算机专业
    js 開始时间,当前时间,结束时间的比較
  • 原文地址:https://www.cnblogs.com/dream1024/p/14051497.html
Copyright © 2020-2023  润新知