Title effect: n-monster, each monster has an ability value a. There are m warriors, each warrior has a strength and endurance S. P Tomorrow can choose a warrior to fight the monster, you must fight the order, if this ability Warriors P> = a then you can beat this monster, we must lay a monster, but only up to a day to play S a monster. If the force P <a. The Warriors came back. End of the day, every warrior can be used many times. Q. How many days requires a minimum, be able to defeat all the monsters all.
A range of data are n (1 <= n <= 2e5), m (1 <= m <= 2e5) (1 <= pi <= 1e9,1 <= si <= n) of all inquiries n + m add up to no more than 2e5
This question is a normal way of thinking (or My general idea is) First, we ask how to solve the minimum time ago i just monsters? ? ? ? ?
Then it can be considered to solve the problem of the i-th monster warrior he addressed intervals, such operations can solve half, then in the maintenance of a segment tree? ? ? ? ?
But this feeling a little difficult to write? And it is easy wa, wa I do not know how many times.
Here is the code written in the game:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <bitset> 7 #include <set> 8 typedef long long ll; 9 using namespace std; 10 const int maxn=201000; 11 int t,n,m; 12 int num[maxn],sum1[maxn<<2],sum2[maxn<<2],dp[maxn],q[maxn],p[maxn],s[maxn]; 13 struct node{ 14 int pi,si; 15 }; 16 node fnum[maxn]; 17 18 bool cmp(node n1,node n2){ 19 if(n1.pi==n2.pi) return n1.si<n2.si; 20 else return n1.pi<n2.pi; 21 } 22 23 void build1(int l,int r,int rt){ 24 if(l==r){ 25 sum1[rt]=num[l]; 26 return; 27 } 28 int mid=(l+r)/2; 29 build1(l,mid,rt<<1); 30 build1(mid+1,r,rt<<1|1); 31 sum1[rt]=max(sum1[rt<<1],sum1[rt<<1|1]); 32 } 33 34 int ask(int l,int r,int rt,int L,int R){ 35 if(L<=l&&r<=R) return sum1[rt]; 36 int mid=(l+r)/2; 37 int ans=0; 38 if(L<=mid) ans=max(ans,ask(l,mid,rt<<1,L,R)); 39 if(R>mid) ans=max(ans,ask(mid+1,r,rt<<1|1,L,R)); 40 return ans; 41 } 42 43 void adds(int l,int r,int rt,int k,int k1){ 44 if(l==r){ 45 sum2[rt]=k1; 46 return; 47 } 48 int mid=(l+r)/2; 49 if(k<=mid) adds(l,mid,rt<<1,k,k1); 50 else adds(mid+1,r,rt<<1|1,k,k1); 51 sum2[rt]=min(sum2[rt<<1|1],sum2[rt<<1]); 52 } 53 54 int Min(int l,int r,int rt,int L,int R){ 55 if(L<=l&&r<=R) return sum2[rt]; 56 int mid=(l+r)/2; 57 int ans=(int)(1e9+7); 58 if(L<=mid) ans=min(ans,Min(l,mid,rt<<1,L,R)); 59 if(R>mid) ans=min(ans,Min(mid+1,r,rt<<1|1,L,R)); 60 return ans; 61 } 62 63 64 bool check(int l,int r){ 65 int q1=ask(1,n,1,l,r); 66 int iscan=(int)(lower_bound(p+1,p+m+1,q1)-p); 67 //if(l==1&&r==2) printf("%d %d %d %d\n",q1,num[1],num[2],iscan); 68 if(iscan>=1&&iscan<=m&&q[iscan]>=(r-l+1)) return true; 69 return false; 70 } 71 72 int main(){ 73 scanf("%d",&t); 74 while(t--){ 75 scanf("%d",&n); 76 for(int i=1;i<=n;i++) scanf("%d",&num[i]); 77 build1(1,n,1); 78 scanf("%d",&m); 79 for(int i=1;i<=m;i++) scanf("%d%d",&fnum[i].pi,&fnum[i].si); 80 sort(fnum+1,fnum+m+1,cmp); 81 int flag=0; 82 for(int i=1;i<=m;i++){ 83 //if(fnum[i].pi<num[i]) flag=1; 84 p[i]=fnum[i].pi;s[i]=fnum[i].si; 85 } 86 for(int i=1;i<=n;i++) if(fnum[m].pi<num[i]) flag=1; 87 if(flag==1){printf("-1\n");continue;} 88 89 q[m]=fnum[m].si; 90 for(int i=m-1;i>=1;i--) q[i]=max(q[i+1],s[i]); 91 92 dp[1]=1;dp[0]=0; 93 adds(0,n,1,1,1); adds(0,n,1,0,0); 94 for(int i=2;i<=n;i++){ 95 int l=1,r=i,ans=i; 96 while(l<=r){ 97 int mid=(l+r)/2; 98 if(check(mid,i)==1){ans=mid;r=mid-1;} 99 else l=mid+1; 100 } 101 // cout<<ans-1<<" "<<i-1<<endl; 102 dp[i]=Min(0,n,1,ans-1,i-1)+1; 103 adds(0,n,1,i,dp[i]); 104 } 105 printf("%d\n",dp[n]); 106 } 107 return 0; 108 }
Then that is a very wonderful solution, I do not know how to think of such a solution in which the exam? ? ? ? ? ?
tql !!!
(1): First, we can find that this thing can be greedy, that is, for every warrior he can kill monsters as possible, all in all is what can be more than just a monster on the number of what the monster, greedy to go directly to ok
(2): Then we need to discard m this stuff, because futile, considering the maximum fi can i days of continuous fighting warrior, so if we can stick i days, go on line and directly, without the need to consider that particular warrior
(3): i directly mapped to the range above, this is best done
Here is the code:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 #include <bitset> 7 typedef long long ll; 8 using namespace std; 9 const int maxn=201000; 10 int num[maxn],mx[maxn]; 11 int t,n,m; 12 int main(){ 13 scanf("%d",&t); 14 while(t--){ 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) scanf("%d",&num[i]); 17 for(int i=1;i<=n;i++) mx[i]=0; 18 scanf("%d",&m); 19 for(int i=1;i<=m;i++){ 20 int pi,si; 21 scanf("%d%d",&pi,&si); 22 mx[si]=max(mx[si],pi); 23 } 24 for(int i=n-1;i>=1;i--) mx[i]=max(mx[i],mx[i+1]); 25 26 int pos=1,flag=1,day=0; 27 while(pos<=n){ 28 day++; int tmp=pos,maxn=0; 29 while(tmp<=n){ 30 maxn=max(maxn,num[tmp]); 31 if(maxn>mx[tmp-pos+1]) break; 32 ++tmp; 33 } 34 if(tmp==pos){ 35 flag=0;break; 36 } 37 pos=tmp; 38 } 39 if(!flag) day=-1; 40 printf("%d\n",day); 41 } 42 return 0; 43 }