[FJOI2015]火星商店问题 --线段树分治+可持久化trie
题意:https://www.luogu.com.cn/problem/P4585
询问有两种限制
1:商店区间限制
2:时间区间限制
思路:
像这样两个限制我们考虑线段树二分(应该是这么考虑吧。。。
线段树二分我的理解其实就是整体二分只不过在线段树上
线段树二分有时候也利用dfs的顺序解题,比如LOJ121(我也就做了这几题=-=
我们把时间放到线段树上就不需要考虑时间了
试问:不需要考虑时间,给你一个询问还不好做吗,二分啊,那n个询问就是整体二分
就没了。。
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin); 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr strcat 13 #include <string> 14 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 #include <cassert> 21 #include <iomanip> 22 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 23 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 24 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 25 //****************** 26 clock_t __START,__END; 27 double __TOTALTIME; 28 void _MS(){__START=clock();} 29 void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;} 30 //*********************** 31 #define rint register int 32 #define fo(a,b,c) for(rint a=b;a<=c;++a) 33 #define fr(a,b,c) for(rint a=b;a>=c;--a) 34 #define mem(a,b) memset(a,b,sizeof(a)) 35 #define pr printf 36 #define sc scanf 37 #define ls rt<<1 38 #define rs rt<<1|1 39 typedef pair<int,int> PII; 40 typedef vector<int> VI; 41 typedef unsigned long long ull; 42 typedef long long ll; 43 typedef double db; 44 const db E=2.718281828; 45 const db PI=acos(-1.0); 46 const ll INF=(1LL<<60); 47 const int inf=(1<<30); 48 const db ESP=1e-9; 49 const int mod=(int)1e9+7; 50 const int N=(int)1e5+10; 51 52 int ans[N]; 53 54 class TRIE 55 { 56 public: 57 int tot; 58 int root[N*20]; 59 int tr[N*20][2]; 60 int sz[N*20]; 61 void Init() 62 { 63 tot=0; 64 sz[0]=root[0]=0; 65 } 66 void insert(int &x,int u,int val) 67 { 68 int now;now=x=++tot; 69 for(int i=17;i>=0;i--) 70 { 71 int d=(val&(1<<i))!=0; 72 tr[now][d^1]=tr[u][d^1];tr[now][d]=++tot; 73 now=tr[now][d];u=tr[u][d]; 74 sz[now]=sz[u]+1; 75 } 76 } 77 int query(int l,int r,int val) 78 { 79 int res=0; 80 for(int i=17;i>=0;i--) 81 { 82 int d=(val&(1<<i))!=0; 83 if(sz[tr[r][d^1]]-sz[tr[l][d^1]]>0) 84 l=tr[l][d^1],r=tr[r][d^1],res+=(1<<i); 85 else l=tr[l][d],r=tr[r][d]; 86 } 87 return res; 88 } 89 }TR; 90 91 vector<vector<int> >Seg(N*4); 92 void update(int L,int R,int val,int l,int r,int rt)//查询区间和 93 { 94 if(L>R)return; 95 if(L<=l&&r<=R) 96 { 97 Seg[rt].push_back(val); 98 return; 99 } 100 int mid=(l+r)>>1; 101 if(L<=mid)update(L,R,val,l,mid,rt<<1); 102 if(R> mid)update(L,R,val,mid+1,r,rt<<1|1); 103 } 104 struct node 105 { 106 int day,shop,v; 107 friend bool operator<(node a,node b) 108 { 109 return a.shop<b.shop; 110 } 111 }goods[N];int cg; 112 struct node0{int l,r,x,L,R;}q[N];int cq; 113 114 int temp[N]; 115 void cal(int rt,int gol,int gor) 116 { 117 int cnt=0; 118 TR.Init(); 119 for(int i=gol;i<=gor;++i)temp[++cnt]=goods[i].shop,TR.insert(TR.root[cnt],TR.root[cnt-1],goods[i].v); 120 for(int i=0,sz=Seg[rt].size();i<sz;++i) 121 { 122 int now=Seg[rt][i]; 123 int l=lower_bound(temp+1,temp+1+cnt,q[now].l)-temp; 124 int r=upper_bound(temp+1,temp+1+cnt,q[now].r)-temp-1; 125 ans[now]=max(ans[now],TR.query(TR.root[l-1],TR.root[r],q[now].x)); 126 } 127 } 128 node t1[N],t2[N]; 129 void solve(int l,int r,int gol,int gor,int rt) 130 { 131 if(gol>gor)return; 132 int cnt1=0,cnt2=0; 133 int mid=(l+r)>>1; 134 cal(rt,gol,gor); 135 if(l==r)return; 136 //左右放 类似整体二分 137 for(int i=gol;i<=gor;i++) 138 { 139 if(goods[i].day<=mid)t1[++cnt1]=goods[i]; 140 else t2[++cnt2]=goods[i]; 141 } 142 //必须按顺序摆放 符合单调性 因为你要二分呀艹 143 for(int i=1;i<=cnt1;i++)goods[i+gol-1]=t1[i]; 144 for(int i=1;i<=cnt2;i++)goods[i+cnt1+gol-1]=t2[i]; 145 solve(l,mid,gol,cnt1+gol-1,ls); 146 solve(mid+1,r,gor-cnt2+1,gor,rs); 147 } 148 149 int main() 150 { 151 int n,m; 152 sc("%d%d",&n,&m); 153 TR.Init(); 154 for(int i=1,temp;i<=n;++i)sc("%d",&temp),TR.insert(TR.root[i],TR.root[i-1],temp); 155 int op; 156 for(int i=1;i<=m;++i) 157 { 158 int l,r,shop,v,d,x; 159 sc("%d",&op); 160 if(op==0)sc("%d%d",&shop,&v),goods[++cg]={cg,shop,v}; 161 else 162 { 163 sc("%d%d%d%d",&l,&r,&x,&d); 164 q[++cq]={l,r,x,max(1,cg-d+1),cg}; 165 ans[cq]=TR.query(TR.root[l-1],TR.root[r],x); 166 } 167 } 168 for(int i=1;i<=cq;++i)update(q[i].L,q[i].R,i,1,cg,1); 169 sort(goods+1,goods+1+cg); 170 solve(1,cg,1,cg,1); 171 for(int i=1;i<=cq;++i)pr("%d\n",ans[i]); 172 return 0; 173 } 174 175 /**************************************************************************************/