每日推荐:https://blog.csdn.net/huzhigenlaohu/article/details/52245070
https://blog.csdn.net/timeclimber/article/details/76281356
https://blog.csdn.net/qq_33997572/article/details/80308382
http://www.bubuko.com/infodetail-406594.html
更多题目:https://blog.csdn.net/timeclimber/article/details/79194495
https://blog.csdn.net/haut_ykc/article/details/76668966
https://blog.csdn.net/jibancanyang/article/details/51893807
https://www.cnblogs.com/elpsycongroo/p/6935682.html
智力异或(2)
Problem:1270
Time Limit:5000ms
Memory Limit:36665535K
Description
有一个数列包含n个正整数a[1]~a[n](1<=n<=1e5,0<=a[i]<1e9),现在有q次操作(q<1e5),每次操作是以下两种操作中的一种:
1、输入x,对这n个数分别异或x;
2、输入k,对数列中前k大个数求和;
Input
第一行为T,表示有T(T<=10)组数据。
每组数据的第一行为n和q,表示这个数列长为n,q次操作。然后输入这n个数。
接下来,每次操作输入一行两个数op(op为1或者2)和x(或者k)(0<=x<1e9,1<=k<=n),op=1表示进行操作1,op=2表示进行操作2;
Output
每次进行操作2时,输出数列中前k大个数的和;
Sample Input
1
4 3
6 7 5 4
1 3
2 2
2 4
Sample Output
13
22
Hint
Source
CJJ
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int trie[maxn*35][3]={0};
int Num[maxn*35][32]= {0};
long long two[40];
int num[maxn*35],cnt =1;
void Trie_insert(int x)
{
int p = 1;
for(int i=31; i>=0; i--)
{
int t = (x>>i)%2;
if(!trie[p][t])trie[p][t] = ++cnt;
p = trie[p][t];
num[p]++;
for(int j=31; j>=0; j--)
{
Num[p][j]+=(x>>j)%2;
}
}
}
void init(){
for(int i=0;i<=cnt;i++)
{
num[i] =0 ;
trie[i][0] = 0;
trie[i][1] = 0;
for(int j=0;j<32;j++)
Num[i][j] = 0;
}
cnt=1;
}
long long Trie_query(int x,int k)
{
int p = 1;
long long ans =0 ;
for(int i=31; i>=0&&k; i--)
{
int t = (x>>i)%2;
if(t==0)
{
if(trie[p][1])
{
if(num[trie[p][1]]<=k)
{
k-=num[trie[p][1]];
for(int j=31; j>=0; j--)
{
int pp = (x>>j)%2;
if(pp==0)
ans+=Num[trie[p][1]][j]*two[j];
else
ans+=(num[trie[p][1]]-Num[trie[p][1]][j])*two[j];
}
p = trie[p][0];
}
else p = trie[p][1];
}
else
p = trie[p][0];
}
else
{
int hh = trie[p][0];
if(hh)
{
if(num[hh]<=k)
{
k-=num[hh];
for(int j=31;j>=0;j--)
{
int pp = (x>>j)%2;
if(pp==0)
{
ans+=Num[hh][j]*two[j];
}
else ans+=(num[hh]-Num[hh][j])*two[j];
}
p = trie[p][1];
}
else p = trie[p][0];
}
else p = trie[p][1];
}
}
if(k)
{
for(int i=31;i>=0;i--)
{
int pp = (x>>i)%2;
if((pp==0&&Num[p][i])||(pp==1&&!Num[p][i]))
{
ans+=two[i]*k;
}
}
}
return ans;
}
int main()
{
two[0] = 1;
for(int i=1;i<32;i++)two[i] = two[i-1]*2;
//freopen("in.txt","r",stdin);
int T,n,m,x;
scanf("%d",&T);
while(T--)
{
int temp = 0;
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=n; i++)
{
scanf("%d",&x);
Trie_insert(x);
}
for(int i=1; i<=m; i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==1)
{
temp^=x;
}
else
{
printf("%lld\n",Trie_query(temp,x));
}
}
}
return 0;
}