zoukankan      html  css  js  c++  java
  • hdu 6059 Kanade's trio

      OwO http://acm.hdu.edu.cn/showproblem.php?pid=6059

      由于每个数字最多是30位,枚举数字每一位考虑,

      建一棵记录前缀(位的前缀,比如10拆成1010,那么就把1010从前往后插入这个字典树中)的字典树,

      nxt记录其后继,gcnt记录这个节点添加的个数,ng代表不符合要减去的个数(后文会提到)

      tol[i][j]代表第i位的j(j=0,1)当前数量

      枚举Ak的每一位,对于Ak的第t位(记作Ak[t])

      1. 如果Ak[t]==1,那么对答案产生贡献的Ai[t]和Aj[t]必然为0,而且Ai[0]~Ai[t-1]必然和Ak[0]~Ak[t-1]对应相等。

       记Ak[t]对应地节点为chil,与其同父亲的另一个节点为xchil

       1) Ak[t]加入后,第一部分要的贡献为 (tree[xchil].gcnt-1)*tree[xchil].gcnt/2 ,这是显然的,就是Ai[0]~Ai[t-1]和Ak[0]~Ak[t-1]和Aj[0]~Aj[t-1]全都相等情况

       2) 第二部分是 tree[xchil].gcnt*(tol[i][1-s[i]]-tree[xchil].gcnt)-tree[xchil].ng ,减号前面的是Ai[0]~Ai[t-1]和Ak[0]~Ak[t-1]相等,且Ak[0]~Ak[t-1]和Aj[0]~Aj[t-1]有所不同的积(这样算出来有不合法的),因为有不合法所以要减去不合法的部分也就是tree[xchi].ng

       而tree[xchi].ng的维护的话,每次加入一个点,那么这个点必然会在当前节点产生 tol[i][s[i]]-tree[chil].gcnt 点不合法的贡献,(Ai[0]~Ai[t-1]和Ak[0]~Ak[t-1]不相等,Ak[0]~Ak[t-1]和Aj[0]~Aj[t-1]相等这种不合法的情况)

      2. 如果Ak[i]==0的话,那么答案也类似可以得到

      

      (思路来自队友DorMOUSENone(队友真是太强辣))

      

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    
    const int M=5e5+55;
    const int N=33;
    const int infn=30;
    
    struct Node
    {
    	int nxt[2],gcnt;
    	ll ng;
    }	tree[M*N];
    
    int n,tnum;
    ll ans;
    int s[N],tol[N][2];
    
    void insert()
    {
    	int rt=0,i,j,chil,xchil;
    	for(i=infn-1;i>=0;i--)
    	{
    		if(tree[rt].nxt[s[i]]==0)
    			tree[rt].nxt[s[i]]=++tnum;
    		chil=tree[rt].nxt[s[i]];	//children for s[i]
    		xchil=tree[rt].nxt[1-s[i]];	//another children
    		if(xchil)
    			ans+=1ll*(tree[xchil].gcnt-1)*tree[xchil].gcnt/2+1ll*tree[xchil].gcnt*(tol[i][1-s[i]]-tree[xchil].gcnt)-tree[xchil].ng;
    		tree[chil].ng+=tol[i][s[i]]-tree[chil].gcnt;
    		tree[chil].gcnt++;
    		tol[i][s[i]]++;
    		rt=chil;
    	}
    }
    
    void init()
    {
    	memset(tree,0,(n+4)*N*sizeof(Node));
    	memset(tol,0,sizeof(tol));
    	tnum=0;
    	ans=0;
    }
    
    void solve()
    {
    	int i,j,now;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&now);
    		for(j=0;j<infn;j++)
    		{
    			s[j]=now&1;
    			now>>=1;
    		}
    		insert();
    	}
    }
    
    int main()
    {
    	int T,now;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		init();
    		solve();
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    /*
    
    200
    4
    1 3 0 0
    
    */
    

      

    327MS代码

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    namespace fastIO {  
        #define BUF_SIZE 100000  
        //fread -> read  
        bool IOerror = 0;  
        inline char nc() {  
            static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;  
            if(p1 == pend) {  
                p1 = buf;  
                pend = buf + fread(buf, 1, BUF_SIZE, stdin);  
                if(pend == p1) {  
                    IOerror = 1;  
                    return -1;  
                }  
            }  
            return *p1++;  
        }  
        inline bool blank(char ch) {  
            return ch == ' ' || ch == '
    ' || ch == '
    ' || ch == '	';  
        }  
        inline void read(int &x) {  
            char ch;  
            while(blank(ch = nc()));  
            if(IOerror)  
                return;  
            for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');  
        }  
        #undef BUF_SIZE  
    };  
    using namespace fastIO; 
    
    
    typedef long long ll;
    
    const int M=5e5+55;
    const int N=33;
    const int infn=30;
    
    struct Node
    {
    	int nxt[2],gcnt;
    	int ng;
    }	tree[M*N];
    
    int n,tnum;
    ll ans;
    int s[N],tol[N][2];
    
    
    void insert()
    {
    	int rt=0,i,j,chil,xchil;
    	for(i=infn-1;i>=0;i--)
    	{
    		if(tree[rt].nxt[s[i]]==0)
    			tree[rt].nxt[s[i]]=++tnum;
    		chil=tree[rt].nxt[s[i]];
    		xchil=tree[rt].nxt[1-s[i]];
    		if(xchil)
    			ans+=1ll*(tree[xchil].gcnt-1)*tree[xchil].gcnt/2+1ll*tree[xchil].gcnt*(tol[i][1-s[i]]-tree[xchil].gcnt)-tree[xchil].ng;
    		tree[chil].ng+=tol[i][s[i]]-tree[chil].gcnt;
    		tree[chil].gcnt++;
    		tol[i][s[i]]++;
    		rt=chil;
    	}
    }
    
    void init()
    {
    	memset(tree,0,(n+4)*N*sizeof(Node));
    	memset(tol,0,sizeof(tol));
    	tnum=0;
    	ans=0;
    }
    
    void solve()
    {
    	int i,j,now;
    	for(i=1;i<=n;i++)
    	{
    		read(now);
    		for(j=0;j<infn;j++)
    		{
    			s[j]=now&1;
    			now>>=1;
    		}
    		insert();
    	}
    }
    
    int main()
    {
    	int T,now;
    	read(T);
    	while(T--)
    	{
    		read(n);
    		init();
    		solve();
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Linux学习笔记(十四)磁盘管理(二):格式化、挂载以及Swap分区
    Linux学习笔记(十三)磁盘管理(一):磁盘分区
    Linux学习笔记(十二)VIM编辑器
    Linux学习笔记(十一)shell基础:管道符、通配符和其他特殊符号
    Linux学习笔记(十)shell基础:历史命令、命令补全、输出重定向、输出重定向
    Linux学习笔记(九)shell基础:echo、命令别名和常用快捷键
    Linux学习笔记(八)Linux常用命令:用户登录查看命令
    Linux学习笔记(七)Linux常用命令:挂载命令
    Linux学习笔记(六)Linux常用命令:关机、重启以及系统运行级别
    Python: 截屏
  • 原文地址:https://www.cnblogs.com/FxxL/p/7271613.html
Copyright © 2011-2022 走看看