Doom HDU - 5239 (找规律+线段树)
题目链接:
题目大意:首先是T组测试样例,然后n个数,m次询问,然后每一次询问给你一个区间,问你这个这段区间的加上上一次的和是多少,查询完之后,这段区间里面的每个数变为原来的平方。
具体思路:这个模数,和正常的模数不一样。
然后通过打表能发现,每个数不断自身平方对p取模后经过有限次 就不会变化了,
测试少于30次
所以也就是说每个节点至多会被更新30次。
注意会爆long long ,需要用unsigned long long .
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define inf 0x3f3f3f3f
4 # define ull unsigned long long
5 # define lson l,mid,rt<<1
6 # define rson mid+1,r,rt<<1|1
7 const int maxn = 4e5+100;
8 const ull mod = 9223372034707292160;
9 struct node
10 {
11 ull sum;
12 int flag;
13 } tree[maxn];
14 ull qsmu(ull t1,ull t2)
15 {
16 ull ans=0ll;
17 while(t2)
18 {
19 if(t2&1)
20 ans=(ans+t1)%mod;
21 t2>>=1;
22 t1=(t1+t1)%mod;
23 }
24 return ans;
25 }
26 ull tot;
27 void up(int rt)
28 {
29 tree[rt].sum=(tree[rt<<1].sum+tree[rt<<1|1].sum)%mod;
30 tree[rt].flag=(tree[rt<<1].flag&tree[rt<<1|1].flag);
31 }
32 void build(int l,int r,int rt)
33 {
34 tree[rt].flag=0;
35 tree[rt].sum=0;
36 if(l==r)
37 {
38 scanf("%lld",&tree[rt].sum);
39 return ;
40 }
41 int mid=l+r>>1;
42 build(lson);
43 build(rson);
44 up(rt);
45 }
46 void update(int l,int r,int rt,int L,int R)
47 {
48 if(R<l||r<L||tree[rt].flag)
49 return ;
50 if(l==r)
51 {
52 ull tmp=tree[rt].sum;
53 tree[rt].sum=qsmu(tree[rt].sum,tree[rt].sum);
54 if(tmp==tree[rt].sum)
55 tree[rt].flag=1;
56 return ;
57 }
58 int mid=(l+r)>>1;
59 update(lson,L,R);update(rson,L,R);
60 up(rt);
61 }
62 void ask(int l,int r,int rt,int L,int R)
63 {
64 if(R<l||r<L)
65 return ;
66 if(L<=l&&R>=r)
67 {
68 tot=(tot+tree[rt].sum)%mod;
69 return ;
70 }
71 int mid=(l+r)>>1;
72 ask(lson,L,R);ask(rson,L,R);
73 up(rt);
74 }
75 int main()
76 {
77 int T;
78 int Case=0;
79 scanf("%d",&T);
80 while(T--)
81 {
82 tot=0;
83 int m,n;
84 scanf("%d %d",&n,&m);
85 build(1,n,1);
86 printf("Case #%d:\n",++Case);
87 while(m--)
88 {
89 int l,r;
90 scanf("%d %d",&l,&r);
91 ask(1,n,1,l,r);
92 printf("%lld\n",tot);
93 update(1,n,1,l,r);
94 }
95 }
96 return 0;
97 }
、