持续更新中…
给你M个点,Q个矩形,每个点都有一个价值,求每个矩形点价值和
首先我们根据N的值和坐标可以O1的得出每个点的价值,这样就转化成了求一个二维矩阵前缀和的问题,由于我们开不了那么大的空间,我们就把第一维X排序,第二维Y扔进树状数组查询前缀和即可,把每个询问拆成四个点询问前缀和矩阵和,然后就可以得出大矩阵的答案了。
#include
#include
#include
#include
#define int long long
const int maxm=1e6+100;
const int N=1e6;
struct node{
int x,y,id,tag;
}a[maxm];
int sum[maxm],ans[maxm];
int n,m,w,cnt,t;
inline int lowbit(int x){return x&(-x);}
inline void ins(int x,int val){for(int i=x;i<=N;i+=lowbit(i)) sum[i]+=val;}
inline int ask(int x){int res=0;for(int i=x;i;i-=lowbit(i)) res+=sum[i];return res;}
inline bool comp(node p,node q){return (p.xq.tag));}
inline int cal(int x,int y)
{
int layer=std::min(std::min(x, y),n-std::max(x, y)+1);
if((layer<<1)>n) return n*n;
int st=n*n-(n-(layer<<1)+2)*(n-(layer<<1)+2)+1;
if (x>=y) return st+((n-layer)<<1)+2-x-y;
return st+((n-(layer<<1)+1)<<1)+x+y-(layer<<1);
}
inline int split(int x)
{
int res=0;
while(x)
{
res+=x%10;
x/=10;
}
return res;
}
inline void work()
{
scanf("%lld%lld%lld",&n,&m,&w);
cnt=0;
memset(sum,0,sizeof(sum));
for(int i=1,x,y;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
a[++cnt]=node{x,y,split(cal(x,y)),2};
}
for(int i=1,x1,y1,x2,y2;i<=w;i++)
{
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
ans[i]=0;
a[++cnt]=node{x2,y2,i,1};
a[++cnt]=node{x2,y1-1,i,-1};
a[++cnt]=node{x1-1,y2,i,-1};
a[++cnt]=node{x1-1,y1-1,i,1};
}
std::sort(a+1,a+cnt+1,comp);
for(int i=1;i<=cnt;i++)
{
if(a[i].tag==2) ins(a[i].y,a[i].id);
else ans[a[i].id]+=a[i].tag*ask(a[i].y);
}
for(int i=1;i<=w;i++) printf("%lld\n",ans[i]);
}
signed main()
{
scanf("%lld",&t);
for(int i=1;i<=t;i++) work();
return 0;
}
求 a ^ a ^ a ^ (…) ^ a 共 b 个a%P的值
欧拉降幂就好了
#include
#include
#define int long long
const int N=1000000;
int phi[N+10],prime[N+10],mark[N+10];
int a,b,p,t,tot;
void getphi()
{
phi[1]=1;
for(int i=2;i<=N;i++)
{
if(!mark[i])
{
prime[++tot]=i;
phi[i]=i-1;
}
for(int j=1;j<=tot&&i*prime[j]<=N;j++)
{
mark[i*prime[j]]=1;
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
inline int fastpow(int x,int y,int mod)
{
int ans=1;
while(y)
{
if(y%2) ans=(ans*x)%mod;
x=(x*x)%mod;
y/=2;
}
return ans;
}
int slove(int a,int b,int p)
{
if(p==1) return 0;
if(b==0) return 1;
int d=slove(a,b-1,phi[p]);
if(d
太长了懒得说
对于每个值,他下面的值是一定的,我们只需要预处理出每个值下面连接的值,然后在这个图上就可以把每个值序列的长度跑出来了。
我们需要查询区间小于一个值的最大值,用主席树就能实现了。
#include
#include
#include
#include
#include
#include
const int maxm=1e5+100;
int n,k;
int val[maxm],ans[maxm];
int root[maxm];
bool in[maxm];
std::vector edge[maxm];
std::queue dl;
struct tree{
int sum[maxm*20],ls[maxm*20],rs[maxm*20];
int sz;
void insert(int &now,int pre,int l,int r,int ind)
{
now=++sz;
ls[now]=ls[pre],rs[now]=rs[pre],sum[now]=sum[pre]+1;
if(l>=r) return;
int mid=(l+r)>>1;
ind<=mid?insert(ls[now],ls[pre],l,mid,ind):insert(rs[now],rs[pre],mid+1,r,ind);
}
int ask_rank(int now,int pre,int l,int r,int ind)
{
int nowsum=sum[now]-sum[pre];
if(r<=ind) return nowsum;
int mid=(l+r)>>1;
if(mid+1<=ind) return ask_rank(ls[now],ls[pre],l,mid,ind)+ask_rank(rs[now],rs[pre],mid+1,r,ind);
else return ask_rank(ls[now],ls[pre],l,mid,ind);
}
int find(int now,int pre,int l,int r,int kth)
{
if(l>=r) return l;
int nowsum=sum[ls[now]]-sum[ls[pre]];
int mid=(l+r)>>1;
if(kth<=nowsum) return find(ls[now],ls[pre],l,mid,kth);
else return find(rs[now],rs[pre],mid+1,r,kth-nowsum);
}
}st;
inline int read()
{
int x=0,w=1;
char ch=0;
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x*w;
}
inline void work()
{
st.sz=0;
n=read(),k=read();
for(int i=1;i<=n;i++) val[i]=read(),ans[i]=0,in[i]=0,edge[i].clear();
for(int i=1;i<=n;i++) st.insert(root[i],root[i-1],1,n,val[i]);
for(int i=1;i<=n;i++)
{
int ql=std::max(1,i-k);
int qr=std::min(n,i+k);
int rank=st.ask_rank(root[qr],root[ql-1],1,n,val[i]);
if(rank!=1)
{
int poi=st.find(root[qr],root[ql-1],1,n,rank-1);
edge[poi].push_back(val[i]);
in[val[i]]=1;
}
}
for(int i=1;i<=n;i++) if(!in[i]) dl.push(i),ans[i]=1;
while(!dl.empty())
{
int now=dl.front();
dl.pop();
for(int i=0;i